home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_186 / simcpm / simcpm1.asm < prev    next >
Assembly Source File  |  1992-05-06  |  101KB  |  3,265 lines

  1. vermaj     equ    $02    ;Major version number
  2. vermin     equ    $30    ;Minor version number
  3. revyear  equ    $89    ;Year last assembled
  4. revmonth equ    $01    ;Month last assembled
  5. revday     equ    $09    ;Day last assembled
  6. *************************************************************************
  7. *                                    *
  8. *                                    *
  9. *    Z-80 Simulator for MC68000                    *
  10. *                                    *
  11. *    With CP/M 2.2 call support, and optional tracing        *
  12. *                                    *
  13. *                                    *
  14. * Amiga version 2.3 (December 1988, Charlie Gibbs):            *
  15. *                                    *
  16. *    Incorporated modifications by Willi Kusche            *
  17. *    (his version 2.1, June 29, 1988):                *
  18. *        Register definitions split into "ecpmdefs.i"        *
  19. *        Improved macro usage                    *
  20. *        Correction of errors in Z-80 flag setting routines    *
  21. *        Incorporated modified trace dump routines        *
  22. *        Allow changing of trace addresses during execution    *
  23. *        Added the following BDOS calls:                *
  24. *            27 - get allocation vector            *
  25. *                (using a fake allocation vector)    *
  26. *            31 - get disk parameter block            *
  27. *                (using a fake disk parameter block)    *
  28. *                                    *
  29. *    Modifications inspired by Ulf Nordquist's CP/M emulator:    *
  30. *          - BDOS calls 17 and 18 (search for first file and        *
  31. *        search for next file) now put file size information    *
  32. *        into the FCB.                        *
  33. *          - BDOS call 27 (get allocation vector) now builds a fake    *
  34. *        allocation vector based on actual volume information.    *
  35. *                                    *
  36. *    The file handle table now also contains the first 12 bytes    *
  37. *    of the FCB to which the handle corresponds.  The FCB is        *
  38. *    no longer modified with a sequence number.            *
  39. *                                    *
  40. *    BDOS call 20 (sequential read) now returns 01h in the        *
  41. *    accumulator when end of file is reached, rather than 0FFh    *
  42. *    as is suggested by CP/M manuals.  Some utilities (such as    *
  43. *    ASM.COM) assume 0FFh indicates an I/O error.            *
  44. *                                    *
  45. *    A new INCLUDE file, options.i, has been added.  This file    *
  46. *    contains EQUate statements which allow you to set options    *
  47. *    that cannot be easily set at execution time.  Current options    *
  48. *    allow inclusion of Heath/Zenith 19 escape code translation,    *
  49. *    and support of 68010 and higher processors by replacing all    *
  50. *    MOVE SR instructions by MOVE CCR.                *
  51. *                                    *
  52. *                                    *
  53. * Amiga version 2.2 (June 1988, Charlie Gibbs):             *
  54. *                                    *
  55. *    BDOS call 23 (rename) was not working properly.         *
  56. *                                    *
  57. *    BIOS and BDOS call messages (for tracing or errors)        *
  58. *    now indicate that the call number is in hexadecimal.        *
  59. *                                    *
  60. *    The following BDOS calls have now been implemented:        *
  61. *        35 - get file end address                *
  62. *        36 - get direct address                 *
  63. *                                    *
  64. *                                    *
  65. * Amiga version 2.1 (May 1988, Charlie Gibbs):                *
  66. *                                    *
  67. *    If a reference is made to any drive other than A:, SimCPM    *
  68. *    will insert the string CPMx: ahead of any file name it uses.    *
  69. *    For instance, if a program tries to open MYFILE.DAT on drive    *
  70. *    B:, SimCPM will try to open CPMB:MYFILE.DAT.  You can ASSIGN    *
  71. *    these simulated drives anywhere you want.  Drive A: will    *
  72. *    always go to the current directory, unless the user number    *
  73. *    is not zero.  If you specify any user number other than zero,    *
  74. *    it will be included, e.g. if the above example were opened    *
  75. *    under user 1, SimCPM will look for CPMB01:MYFILE.DAT.        *
  76. *    If the file were on drive A under user 1, SimCPM will look    *
  77. *    for CPMA01:MYFILE.DAT.                        *
  78. *                                    *
  79. *    If the file handle table overflowed, the file which caused    *
  80. *    the overflow has already been opened.  It was not being     *
  81. *    closed again.  This file is now closed before the emulated    *
  82. *    program is aborted.                        *
  83. *                                    *
  84. *    If an emulated program failed to close all the files it opened, *
  85. *    the emulator would close these files.  However, it did not    *
  86. *    clear the open flag for any such files.  If another program    *
  87. *    was then run, when it terminated the emulator would try to    *
  88. *    close these same files again.  This bug has been corrected.    *
  89. *                                    *
  90. *    Z-80 instructions not supported by version 2.0 have been    *
  91. *    implemented as follows:                     *
  92. *        LD I,A moves to a dummy interrupt register.        *
  93. *        LD A,I moves from a dummy interrupt register.        *
  94. *        LD R,A is ignored.                    *
  95. *        LD A,R moves a random value from the clock into     *
  96. *            the low-order 7 bits of the accumulator.    *
  97. *        IM1 and IM2 are ignored.                *
  98. *                                    *
  99. *    The -z command-line switch has been implemented.        *
  100. *    It sets instruction tracing, just like the -t switch,        *
  101. *    but causes Z-80 instruction mnemonics to be used.        *
  102. *    If this switch is not set, 8080 mnemonics are used.        *
  103. *                                    *
  104. *    BDOS call 32 (get or set user code) is now fully implemented.    *
  105. *                                    *
  106. *    The following BDOS calls have now been implemented:        *
  107. *        13 - reset all drives                    *
  108. *        24 - get active drive map                *
  109. *        28 - protect drive                    *
  110. *        29 - get read-only drive map                *
  111. *                                    *
  112. *    The USER and SAVE built-in commands have been implemented.    *
  113. *    These are the only build-in commands provided, since commands    *
  114. *    such as DIR or TYPE can be handled through a CLI window.    *
  115. *                                    *
  116. *                                    *
  117. * Amiga version 2.0 (January 1988, Charlie Gibbs):            *
  118. *                                    *
  119. *    Added all Z-80 instructions except the following:        *
  120. *        LD A,I                            *
  121. *        LD I,A                            *
  122. *        LD A,R                            *
  123. *        LD R,A                            *
  124. *        IM1                            *
  125. *        IM2                            *
  126. *                                    *
  127. *    Added -t flag for tracing without needing            *
  128. *        a separate version to maintain speed.            *
  129. *                                    *
  130. *    Added the following BDOS calls:                 *
  131. *        17 - search for first file                *
  132. *        18 - search for next file                *
  133. *        24 - get active drive map                *
  134. *            (assumes only drive A: is active)        *
  135. *        28 - protect drive (ignored)                *
  136. *        29 - get read-only map                    *
  137. *            (assumes no drives are protected)        *
  138. *        32 - get or set user code                *
  139. *            (always gets user code zero, any attempt    *
  140. *            to set to a user code other than zero        *
  141. *            results in a fatal error)            *
  142. *                                    *
  143. *    Added serial port support (simulated 8251 on ports 14 and 15)    *
  144. *                                    *
  145. *                                    *
  146. *    Converted to AmigaDOS September 1987 by Charlie Gibbs        *
  147. *    (after painstakingly typing it all in from Dr. Dobbs        *
  148. *    Journal, January through March 1986).  Improvements        *
  149. *    described by Jim Cathey in his letter in the June 1986        *
  150. *    DDJ have been included.  Repetitive code is generated        *
  151. *    by macros whenever it would save my fingers.            *
  152. *                                    *
  153. *                                    *
  154. *    Version 1.2 1/21/85 JEC                     *
  155. *        Fixed Extent bug in OPEN logic.             *
  156. *        Sped up code, sample MAC from 2:13 to 1:40        *
  157. *        Now runs at a 1.4 MHz equivalent based on MAC sample.    *
  158. *                                    *
  159. *    Version 1.1 8/29/84 JEC                     *
  160. *        Fixed BIOS call #6 bug.                 *
  161. *                                    *
  162. *    Version 1.0 05/25/84 by Jim Cathey                *
  163. *                                    *
  164. *    This program has been written for speed whenever possible,    *
  165. *    as such tends to be large because of the separate subroutine    *
  166. *    for each and every opcode of the target processor.        *
  167. *                                    *
  168. *    On an 8MHz 68000 (Compupro) system the simulation speed is    *
  169. *    a little better than a 1MHz Z-80 when running MAC.  The time    *
  170. *    for a sample assembly was 2:13 for the simulation vs. 0:35    *
  171. *    on a 4MHz Z-80, both systems used identical hard disk systems.    *
  172. *                                    *
  173. *    It is not a complete simulation, as some flag handling        *
  174. *    isn't quite right, but it is enough to run the program        *
  175. *    I wrote for it (DDT, LU, MAC, and Morrow's FORMATW).        *
  176. *                                    *
  177. *************************************************************************
  178.     code
  179.     page
  180. *************************************************************************
  181. *                                    *
  182. *    This file contains the startup routines, the simulator core,    *
  183. *    tracing code, and the CP/M 2.2 simulation.            *
  184. *                                    *
  185. *************************************************************************
  186.  
  187.     xref    optabl,flags,mloop,mloopt,tracesad,traceead,traceflg,start2
  188.     xdef    illegl,service,dump,inp,outp,movear
  189.  
  190.     xref    _AbsExecBase
  191.     xref    _CreatePort
  192.     xref    _DeletePort
  193.     xdef    _SysBase
  194.     xdef    _DOSBase
  195.  
  196.     include    "options.i"
  197.     include    "ecpmdefs.i"
  198.  
  199. *
  200. * ASCII character values
  201. *
  202. bel    equ    $07        ;Bell (or beep or whatever)
  203. bs    equ    $08        ;Backspace
  204. ht    equ    $09        ;Horizontal tab
  205. lf    equ    $0A        ;Line feed
  206. ff    equ    $0C        ;Form feed
  207. cr    equ    $0D        ;Carriage return
  208. so    equ    $0E        ;Shift out
  209. si    equ    $0F        ;Shift in
  210. esc    equ    $1B        ;Escape
  211.     page
  212. *--------------------------------
  213. *
  214. * Some commonly used macros
  215. *
  216. *--------------------------------
  217.  
  218. sys    macro            ;Call a system routine.
  219.     ifnd    _LVO\1
  220.     xref    _LVO\1
  221.     endc
  222.     jsr    _LVO\1(a6)
  223.     endm
  224.  
  225. *----------------------------
  226. * Target system Mnemonics
  227. *----------------------------
  228. tHLT    EQU    $76
  229. tJMP    EQU    $C3
  230. tRET    EQU    $C9
  231.  
  232. *----------------------
  233. * Equates
  234. *----------------------
  235.  
  236. MODE_OLDFILE equ 1005
  237. MODE_NEWFILE equ 1006
  238. ACCESS_READ  equ -2
  239. ACCESS_WRITE equ -1
  240. STARTBAUD equ    1200        ;Starting baud rate
  241. NUMBITS equ    8        ;Number of data bits
  242. CTLCHAR equ    $11130501    ;XON, XOFF, ENQ, ACK
  243. SERFLAGS equ    $A0        ;No XON/XOFF, shared
  244. PARITYON equ    1        ;Parity enabled
  245. PARITYODD equ    2        ;Odd parity
  246. * I/O command codes
  247. CMD_INVALID equ 0
  248. CMD_RESET   equ 1
  249. CMD_READ    equ 2
  250. CMD_WRITE   equ 3
  251. CMD_UPDATE  equ 4
  252. CMD_CLEAR   equ 5
  253. CMD_STOP    equ 6
  254. CMD_START   equ 7
  255. CMD_FLUSH   equ 8
  256. CMD_NONSTD  equ 9
  257. SDCMD_QUERY equ CMD_NONSTD
  258. SDCMD_BREAK equ CMD_NONSTD+1
  259. SDCMD_SETPARAMS equ CMD_NONSTD+2 ;Set serial port parameters
  260.     page
  261. *************************************************************************
  262. *                                    *
  263. *    Initialization                            *
  264. *                                    *
  265. *************************************************************************
  266.  
  267. start:    move.l    sp,savesp    ;Save the stack pointer.
  268.     move.l    _AbsExecBase,a6
  269.     move.l    a6,_SysBase    ;Working copy of _AbsExecBase
  270.     move.b    #1,testdol    ;"pstring" should test for leading $.
  271.     clr.w    esclen        ;No partial escape sequence is saved.
  272.     clr.b    insflag     ;We're not in insert mode.
  273.     clr.b    traceit     ;Clear trace request flag.
  274.     clr.b    z80flag     ;Clear Z-80 flag.
  275.     clr.b    btrcflg     ;Turn off BIOS/BDOS call tracing.
  276.     clr.b    quitflg     ;Clear the quit flag.
  277.     clr.b    bufflag     ;Disable output buffering.
  278.     clr.b    listopn     ;The list device is closed.
  279.     clr.b    frstset     ;First call to "setbaud"
  280.     clr.b    target+4    ;Set default drive and user to A0:.
  281.     move.w    #1,acmap    ;Set active drive map to A: only.
  282.     clr.w    romap        ;No drives are set read-only.
  283.     move.l    #STARTBAUD,baud ;Initial serial port parameters
  284.     move.b    #NUMBITS,bits
  285.     move.l    #strbuf,strptr    ;Initialize output buffer pointer.
  286.  
  287.     lea    handles,a1
  288.     move.w    #(handlen-handles)/4-1,d1
  289. 1$    clr.l    (a1)+        ;Clear file handles.
  290.     dbra    d1,1$
  291.     clr.l    rawhand     ;Clear RAW: handle too.
  292.  
  293. *
  294. * Copy the command line to "cmdline", stripping out leading switches if any.
  295. *
  296.     lea    cmdline,a1
  297.     subq    #1,d0
  298. * Skip over leading blanks, if any.
  299. leadblk cmpi.b    #' ',(a0)+    ;Leading blank?
  300.     bne.s    setbuf        ;No.
  301.     dbra    d0,leadblk    ;Skip over leading blank.
  302. *  If the -b switch is given, activate output buffering.
  303. setbuf    subq.l    #1,a0        ;Back onto the first non-blank.
  304.     cmpi.b    #'-',(a0)    ;Possible buffer switch?
  305.     bne.s    savecmd     ;No - start saving the command line.
  306.     cmpi.b    #'B',1(a0)    ;Activate output buffering?
  307.     beq.s    1$        ;Yes.
  308.     cmpi.b    #'b',1(a0)
  309.     bne.s    settrc        ;No.
  310. 1$    move.b    #1,bufflag    ;Set buffered-output flag.
  311.     bra.s    skipsw
  312. * If the -t switch is given, set "traceit".
  313. settrc    cmpi.b    #'T',1(a0)
  314.     beq.s    1$
  315.     cmpi.b    #'t',1(a0)
  316.     bne.s    setz80
  317. 1$    move.b    #1,traceit    ;Set trace flag.
  318. * If the -z switch is given, set both "z80flag" and "traceit".
  319. setz80    cmpi.b    #'Z',1(a0)
  320.     beq.s    1$
  321.     cmpi.b    #'z',1(a0)
  322.     bne.s    skipsw
  323. 1$    move.b    #1,z80flag    ;Set Z-80 flag.
  324.     move.b    #1,traceit    ;Set trace flag also.
  325. * Skip over the switch and check for more.
  326. skipsw    cmpi.b    #' ',(a0)+    ;End of switch?
  327.     beq.s    1$        ;Yes.
  328.     dbra    d0,skipsw
  329.     addq.l    #1,a1        ;Adjust A1.
  330.     bra.s    gotcmd        ;There is no command line left.
  331. 1$    subq.l    #1,a0        ;Back onto the first blank.
  332.     bra.s    leadblk     ;Look for the next non-blank.
  333. * Save the command line (except for leading switches).
  334. savecmd move.b    (a0)+,(a1)+    ;Save the command line, if any.
  335.     dbra    d0,savecmd
  336. gotcmd    move.b    #0,-1(a1)    ;Replace the newline with a null.
  337.     move.b    cmdline,cmdflag ;Save command-line flag.
  338.  
  339. *
  340. * Open libraries and set up a RAW: window.
  341. *
  342.     move.b    #1,quitflg    ;Quit immediately if failure below.
  343.     move.l    _SysBase,a6    ;Find library
  344.     lea    dosname,a1    ;'dos.library'
  345.     moveq    #0,d0        ;Any version
  346.     sys    OpenLibrary    ;Open dos.library.
  347.     move.l    d0,a6        ;Point to doslib for next operation.
  348.     move.l    d0,_DOSBase    ;Save it for future reference.
  349.     sys    Input        ;Get file handle for keyboard.
  350.     move.l    d0,stdin    ;Save it here.
  351.     beq    quitprg     ;Couldn't get keyboard handle.
  352.     sys    Output        ;Get file handle for screen.
  353.     move.l    d0,stdout    ;Save it here.
  354.     beq    quitprg     ;Couldn't get screen handle.
  355.     move.l    #loadmsg,d1
  356.     bsr    pstring     ;Display where we loaded.
  357.     move.l    #start,d1
  358.     bsr    plong
  359.     bsr    pspace
  360.     move.b    #'/',d1
  361.     bsr    pchar
  362.     bsr    pspace
  363.     move.l    #start2,d1
  364.     bsr    plong
  365.     bsr    pcrlf
  366.     move.l    #rawspec,d1
  367.     move.l    #MODE_NEWFILE,d2
  368.     sys    Open        ;Open a RAW: window.
  369.     move.l    d0,rawhand    ;Save the file handle here.
  370.     bne    opened        ;We succeeded.
  371.     move.l    #rawerr,d1
  372.     bsr    pstring     ;Display error message...
  373.     sys    IoErr
  374.     move.l    d0,d1
  375.     bsr    plong        ; and error code.
  376.     bsr    pcrlf
  377.     bra    quitprg
  378.  
  379. dosname dc.b    'dos.library',0
  380. loadmsg dc.b    'SimCPM version '
  381.     dc.b    vermaj&15+'0','.',vermin/16+'0',vermin&15+'0'
  382.     dc.b    ' has loaded at $'
  383. rawspec dc.b    'RAW:0/0/640/200/CP/M Emulator'
  384.     dc.b    ' by Jim Cathey and Charlie Gibbs - version '
  385.     dc.b    vermaj&15+'0','.'
  386.     dc.b    vermin/16+'0',vermin&15+'0',' ('
  387.     dc.b    revyear/16+'0',revyear&15+'0','/'
  388.     dc.b    revmonth/16+'0',revmonth&15+'0','/'
  389.     dc.b    revday/16+'0',revday&15+'0',')',0
  390. rawerr    dc.b    'Unable to open RAW: - code $'
  391. setwin    dc.b    $9B,'0x',$9B,'8y',$9B,'24t',$9B,'80u',$9B,'H',$9B,'J$'
  392.  
  393. opened    move.b    cmdflag,quitflg ;If we have a command, execute it and quit.
  394.     move.l    #setwin,d1
  395.     bsr    pstring     ;Set the window to 24 by 80.
  396.  
  397. *
  398. * Come back here to load another program.
  399. *
  400. nextprg lea    target,targbase ;Start of target memory
  401.     clr.b    insflag     ;Reset insert mode.
  402.     move.l    #simsg,d1
  403.     bsr    pstring     ;In case last program sent SHIFT OUT
  404.     clr.b    dumpcnt     ;Reset dump pause counter.
  405.     clr.l    rpport        ;serial.device message port pointers
  406.     clr.l    wpport
  407.     bsr    entrads     ;Enter trace delimiting addresses.
  408.     bsr    lodfdos     ;Load up the fake FDOS in target memory.
  409.     bsr    lodregs     ;Load the remaining simulation registers.
  410.     bsr    loadcom     ;Load the .COM program.
  411.     jmp    (return)    ;Execute the simulation.
  412.  
  413. simsg    dc.b    si,'$'        ;Resets MSB of each output character
  414.     page
  415. *************************************************************************
  416. *                                    *
  417. *    Illegal instructions and dumping                *
  418. *                                    *
  419. *************************************************************************
  420.  
  421. illegl    move.l    #illgmsg,d1    ;Illegal opcode, say what & where,
  422.     bsr    pstring
  423.     lea    -1(pseudopc),a0
  424.     move.b    (a0),d1
  425.     bsr    pbyte
  426.     cmpi.b    #$CB,(a0)    ;Display sub-op-code for prefixes CB...
  427.     beq.s    1$
  428.     cmpi.b    #$DD,(a0)    ;DD...
  429.     beq.s    1$
  430.     cmpi.b    #$ED,(a0)    ;ED...
  431.     beq.s    1$
  432.     cmpi.b    #$FD,(a0)    ;and FD.
  433.     bne.s    2$
  434. 1$    move.b    1(a0),d1
  435.     bsr    pbyte
  436. 2$    move.l    #ilgmsg2,d1
  437.     bsr    pstring
  438.     suba.l    targbase,a0
  439.     move.l    a0,d1
  440.     bsr    pword
  441.     move.l    #ilgmsg3,d1
  442.     bsr    pstring
  443.     move.l    #dumpmsg,d1
  444.     bsr    pstring
  445.     clr.b    dumpcnt
  446.     bsr    dump        ; and spill guts.
  447.     bra    quitprg     ;Quit simulation.
  448.  
  449. illgmsg dc.b    cr,lf,'Illegal instruction $'
  450. ilgmsg2 dc.b    ' at $'
  451. ilgmsg3 dc.b    '.$'
  452. dumpmsg dc.b    cr,lf,'Register contents:$'
  453.  
  454. *
  455. * Dump all registers and decode the current instruction.
  456. *
  457. dump    movem.l    d0-d3/a1,-(sp)
  458.     bsr    pcrlf
  459.     move.b    regf,d0
  460.     bsr    dspflag
  461.     move.b    #'A',(a0)+
  462.     move.b    #'=',(a0)+
  463.     move.b    rega,d1        ;Accumulator
  464.     bsr    ubyte
  465.     move.b    #' ',(a0)+
  466.     move.b    #'B',(a0)+
  467.     move.b    #'=',(a0)+
  468.     move.w    regb(regs),d1    ;BC
  469.     bsr    uword
  470.     move.b    #' ',(a0)+
  471.     move.b    #'D',(a0)+
  472.     move.b    #'=',(a0)+
  473.     move.w    regd(regs),d1    ;DE
  474.     bsr    uword
  475.     move.b    #' ',(a0)+
  476.     move.b    #'H',(a0)+
  477.     move.b    #'=',(a0)+
  478.     move.w    regh(regs),d1    ;HL
  479.     bsr    uword
  480.     move.b    #' ',(a0)+
  481.     move.b    #'S',(a0)+
  482.     move.b    #'=',(a0)+
  483.     move.l    pseudosp,d1    ;SP
  484.     sub.l    targbase,d1
  485.     bsr    uword
  486.     move.b    #' ',(a0)+
  487.     move.b    #'P',(a0)+
  488.     move.b    #'=',(a0)+
  489.     move.l    pseudopc,d1    ;PC
  490.     sub.l    targbase,d1
  491.     bsr    uword
  492.     move.b    #' ',(a0)+
  493.     move.l    a1,-(sp)
  494.     move.l    pseudosp,a1
  495.     moveq    #3,d2
  496.     moveq    #'0',d3
  497. tosloop    move.b    #'S',(a0)+    ;Display the top 4 stack entries.
  498.     move.b    d3,(a0)+
  499.     addq.b    #1,d3
  500.     move.b    #'=',(a0)+
  501.     move.b    1(a1),d1 
  502.     ror.w    #8,d1
  503.     move.b    0(a1),d1
  504.     bsr    uword
  505.     move.b    #' ',(a0)+
  506.     addq.l    #2,a1
  507.     dbra    d2,tosloop
  508.     move.b    #'$',(a0)+
  509.     move.l    (sp)+,a1
  510.     move.l    #workbuf,d1
  511.     bsr    pstring     ;Displaying as a single string is much faster.
  512.     bsr    pcrlf
  513.     move.b    regf2(regs),d0    ;Alternate flags
  514.     bsr    dspflag
  515.     move.b    #'A',(a0)+
  516.     move.b    #'''',(a0)+
  517.     move.b    rega2(regs),d1    ;Alternate accumulator
  518.     bsr    ubyte
  519.     move.b    #' ',(a0)+
  520.     move.b    #'B',(a0)+
  521.     move.b    #'''',(a0)+
  522.     move.w    regb2(regs),d1    ;Alternate BC
  523.     bsr    uword
  524.     move.b    #' ',(a0)+
  525.     move.b    #'D',(a0)+
  526.     move.b    #'''',(a0)+
  527.     move.w    regd2(regs),d1    ;Alternate DE
  528.     bsr    uword
  529.     move.b    #' ',(a0)+
  530.     move.b    #'H',(a0)+
  531.     move.b    #'''',(a0)+
  532.     move.w    regh2(regs),d1    ;Alternate HL
  533.     bsr    uword
  534.     move.b    #' ',(a0)+
  535.     move.b    #'X',(a0)+
  536.     move.b    #'=',(a0)+
  537.     move.w    regix(regs),d1    ;IX
  538.     bsr    uword
  539.     move.b    #' ',(a0)+
  540.     move.b    #'Y',(a0)+
  541.     move.b    #'=',(a0)+
  542.     move.w    regiy(regs),d1    ;IY
  543.     bsr    uword
  544.     move.b    #' ',(a0)+
  545.     move.b    #' ',(a0)+
  546.     move.b    (pseudopc),d1    ;Current opcode byte
  547.     cmpi.b    #$CB,d1     ;Prefix?
  548.     beq.s    oppfx        ;Yes.
  549.     cmpi.b    #$DD,d1
  550.     beq.s    oppfx
  551.     cmpi.b    #$ED,d1
  552.     beq.s    oppfx
  553.     cmpi.b    #$FD,d1
  554.     beq.s    oppfx
  555.     move.b    #' ',(a0)+
  556.     bsr    ubyte        ;Unprefixed opcode
  557.     move.b    #' ',(a0)+
  558.     bra.s    opx
  559. oppfx    bsr    ubyte        ;Prefix
  560.     move.b    1(pseudopc),d1
  561.     bsr    ubyte        ;Prefixed opcode
  562. opx    move.b    #' ',(a0)+
  563. *
  564. * Decode the instruction.
  565. *
  566.     moveq    #0,d0
  567.     move.b    (pseudopc),d0    ;Opcode
  568.     clr.b    prefix        ;Assume it's not a prefix.
  569.     cmpi.b    #$DD,d0     ;Is it?
  570.     beq.s    dopfx        ;Yes.
  571.     cmpi.b    #$FD,d0
  572.     bne.s    saveop        ;No.
  573. dopfx    move.b    d0,prefix    ;It's a prefix.
  574.     move.b    1(pseudopc),d0    ;The opcode is really here.
  575. saveop    move.b    d0,opcode    ;Save the opcode.
  576. * Look up the opcode.
  577.     cmpi.b    #$40,d0     ;Is opcode in range 00-3F?
  578.     bcc.s    lookupC     ;No.
  579. * The opcode is in the range 00-3F.
  580.     lea    mnop008,a1    ;Assume we're using 8080 mnemonics.
  581.     tst.b    z80flag     ;Should we use Z-80 mnemonics?
  582.     beq.s    lokup0c     ;No
  583.     lea    mnop00z,a1
  584. lokup0c mulu    #12,d0        ;Offset into opcode table
  585.     add.l    d0,a1        ;A1 points to decoded instruction
  586.     bra    decode        ;Decode remainder of instruction.
  587. * The opcode is in the range C0-FF.
  588. lookupC cmpi.b    #$C0,d0     ;Is opcode in range C0-FF?
  589.     bcs.s    lookup8     ;No.
  590.     cmpi.b    #$ED,d0     ;ED-prefix instructions?
  591.     beq    lookupE     ;Yes.
  592.     cmpi.b    #$CB,d0     ;CB-prefix instructions?
  593.     beq    lookupB     ;Yes.
  594.     lea    mnopC08,a1    ;Assume we're using 8080 mnemonics.
  595.     tst.b    z80flag     ;Should we use Z-80 mnemonics?
  596.     beq.s    lokupCc     ;No.
  597.     lea    mnopC0z,a1
  598. lokupCc subi.w    #$C0,d0
  599.     mulu    #12,d0        ;Offset into opcode table
  600.     add.l    d0,a1        ;A1 points to decoded instruction
  601.     bra    decode        ;Decode remainder of instruction.
  602. * The opcode is in the range 80-BF.
  603. lookup8 cmpi.b    #$80,d0     ;Is opcode in range 80-BF?
  604.     bcs.s    lookup4     ;No - it's in range 40-7F.
  605.     lea    mnop808,a1    ;Assume we're using 8080 mnemonics.
  606.     tst.b    z80flag     ;Are we?
  607.     beq.s    lokup8c     ;Yes.
  608.     lea    mnop80z,a1    ;Use the Z-80 mnemonic table.
  609. lokup8c lsr.b    #3,d0        ;Divide opcode by 8.
  610.     andi.w    #7,d0        ;Instruction type
  611.     mulu    #9,d0        ;Offset into opcode table
  612.     add.l    d0,a1        ;A1 points to decoded instruction
  613.     bra    decode        ;Decode remainder of instruction.
  614. * The opcode is in the range 40-7F.
  615. lookup4 cmpi.b    #$76,d0     ;Is this a HLT (Z-80 HALT) instruction?
  616.     bne.s    lokup4m     ;No.
  617.     lea    mnop768,a1
  618.     tst.b    z80flag     ;Do the Z-80 mnemonic?
  619.     beq    decode        ;No.
  620.     lea    mnop76z,a1
  621.     bra    decode
  622. lokup4m lea    mnop408,a1    ;Assume 8080 MOV instruction.
  623.     tst.b    z80flag     ;Are we doing Z-80 mnemonics?
  624.     beq    decode        ;No.
  625.     lea    mnop40z,a1    ;Make it a Z-80 LD instruction.
  626.     bra    decode
  627. * CB-prefix instruction decoding
  628. lookupB move.b    1(pseudopc),d0    ;Sub-opcode
  629.     tst.b    prefix        ;IX or IY with displacement?
  630.     beq.s    lokupB0     ;No.
  631.     move.b    2(pseudopc),d0    ;Skip over the displacement.
  632. lokupB0 move.b    d0,opcode
  633.     cmpi.b    #$40,d0     ;Is opcode in range CB00-CB3F?
  634.     bcc.s    lokupB4     ;No.
  635.     lea    mnopCB08,a1
  636.     lsr.b    #3,d0
  637.     mulu    #8,d0
  638.     add.l    d0,a1
  639.     bra    decode
  640. lokupB4 move.b    d0,d1        ;Save the sub-opcode.
  641.     andi.w    #$C0,d0     ;Opcode is in range CB40-CBFF.
  642.     lsr.b    #3,d0        ;Displacement into 8-byte entries
  643.     lea    mnopCB48,a1
  644.     add.l    d0,a1
  645. lokupBm move.b    (a1)+,(a0)+    ;Move mnemonic to decoded area.
  646.     cmpi.b    #'$',(a1)
  647.     bne.s    lokupBm
  648.     move.b    d1,d0        ;Get the sub-opcode again.
  649.     andi.w    #$38,d0     ;Isolate the bit number.
  650.     lsr.b    #3,d0
  651.     addi.b    #'0',d0     ;Convert the bit number to ASCII.
  652.     move.b    d0,(a0)+    ;Move bit number to decoded instruction.
  653.     move.b    #',',(a0)+
  654.     move.b    d1,d0
  655.     andi.b    #7,d0        ;Isolate the register specification.
  656.     bsr    dspreg        ;Set up the register number.
  657.     bra    dispop
  658. * ED-prefix instruction decoding
  659. lookupE move.b    1(pseudopc),d0    ;Sub-opcode
  660.     move.b    d0,opcode
  661.     cmpi.b    #$40,d0     ;Is it below ED40?
  662.     bcs    lookupI     ;Yes - it's illegal.
  663.     cmpi.b    #$80,d0     ;Is it in range ED40-ED7F?
  664.     bcc    lokupE8     ;No.
  665.     lea    mnopE48,a1    ;Assume we're using 8080 mnemonics.
  666.     tst.b    z80flag     ;Should we use Z-80 mnemonics?
  667.     beq.s    lokupEc     ;No
  668.     lea    mnopE4z,a1
  669. lokupEc andi.w    #$3F,d0
  670.     mulu    #12,d0        ;Offset into opcode table
  671.     add.l    d0,a1        ;A1 points to decoded instruction
  672.     bra    decode        ;Decode remainder of instruction.
  673. lokupE8 cmpi.b    #$A0,d0     ;Is opcode in range ED80-ED9F?
  674.     bcs    lookupI     ;Yes - it's illegal.
  675.     cmpi.b    #$BC,d0     ;It must be in range EDA0-EDBB.
  676.     bcc    lookupI
  677.     lea    mnopEA8,a1
  678.     andi.w    #$1F,d0
  679.     mulu    #5,d0
  680.     add.l    d0,a1
  681.     cmpi.b    #' ',(a1)    ;Is opcode blank?
  682.     bne.s    decode        ;No - decode the instruction.
  683. * The instruction is illegal.
  684. lookupI lea    mnopilg,a1    ;Point to "ILLEGAL" message.
  685. *
  686. * Decode the instruction according to the string pointed to by A1.
  687. *  The decoded instruction is built where A0 points.
  688. *  See the mnemonic tables for an explanation of operand codes.
  689. *
  690. decode:
  691. * Code "r" - register in bits 0-2 of opcode
  692.     cmpi.b    #'r',(a1)
  693.     bne.s    decodeq
  694.     move.b    opcode,d0
  695.     bsr    dspreg
  696.     bra    decodex
  697. * Code "q" - register in bits 3-5 of opcode
  698. decodeq cmpi.b    #'q',(a1)
  699.     bne.s    decodep
  700.     move.b    opcode,d0
  701.     lsr.b    #3,d0
  702.     bsr    dspreg
  703.     bra    decodex
  704. * Code "p" - register pair in bits 4-5 of opcode
  705. decodep cmpi.b    #'p',(a1)
  706.     bne    decodeh
  707.     move.b    opcode,d0
  708.     andi.b    #$30,d0     ;Isolate the register bits.
  709.     bne.s    decodpd     ;They aren't 00.
  710.     move.b    #'B',(a0)+    ;00 - register B
  711.     tst.b    z80flag     ;Are we using Z-80 mnemonics?
  712.     beq    decodex     ;No.
  713.     move.b    #'C',(a0)+    ;Call it BC for Z-80.
  714.     bra    decodex
  715. decodpd cmpi.b    #$20,d0
  716.     beq.s    decodph
  717.     bhi.s    decodps
  718.     move.b    #'D',(a0)+    ;01 - register D (DE for Z-80)
  719.     tst.b    z80flag
  720.     beq    decodex
  721.     move.b    #'E',(a0)+
  722.     bra    decodex
  723. decodph cmpi.b    #$DD,prefix    ;10 - check for index prefix.
  724.     beq.s    decodpx     ;IX
  725.     bhi.s    decodpy     ;IY
  726.     move.b    #'H',(a0)+    ;Register H (HL for Z-80)
  727.     tst.b    z80flag
  728.     beq    decodex
  729.     move.b    #'L',(a0)+
  730.     bra    decodex
  731. decodpx move.b    #'I',(a0)+    ;IX
  732.     move.b    #'X',(a0)+
  733.     bra    decodex
  734. decodpy move.b    #'I',(a0)+    ;IY
  735.     move.b    #'Y',(a0)+
  736.     bra    decodex
  737. decodps cmpi.b    #$F0,opcode    ;11 - depends on opcode
  738.     bcc.s    decodpp
  739.     move.b    #'S',(a0)+    ;11 is SP if opcode is less than F0.
  740.     move.b    #'P',(a0)+
  741.     bra    decodex
  742. decodpp tst.b    z80flag     ;Otherwise, it's PSW (AF for Z-80).
  743.     bne.s    decodpz
  744.     move.b    #'P',(a0)+
  745.     move.b    #'S',(a0)+
  746.     move.b    #'W',(a0)+
  747.     bra.s    decodex
  748. decodpz move.b    #'A',(a0)+
  749.     move.b    #'F',(a0)+
  750.     bra.s    decodex
  751. * Code "h" - HL, IX, or IY depending on prefix
  752. decodeh cmpi.b    #'h',(a1)
  753.     bne.s    decoden
  754.     cmpi.b    #$DD,prefix
  755.     beq.s    decodpx     ;IX
  756.     bhi.s    decodpy     ;IY
  757.     move.b    #'H',(a0)+    ;HL
  758.     move.b    #'L',(a0)+
  759.     bra    decodex
  760. * Code "n" - 8-bit value following opcode
  761. decoden cmpi.b    #'n',(a1)
  762.     bne.s    decodea
  763.     move.b    1(pseudopc),d1
  764.     tst.b    prefix        ;DD or FD prefix?
  765.     beq.s    1$        ;No - we have the value.
  766.     cmpi.b    #$36,opcode    ;Is opcode below 36?
  767.     bcs.s    1$        ;Yes - it's a move to index register half
  768.     move.b    3(pseudopc),d1    ;The value is actually here.
  769. 1$    bsr    ubyte        ;Convert the value to a hex string.
  770.     bra.s    decodex
  771. * Code "a" - 16-bit value following opcode
  772. decodea cmpi.b    #'a',(a1)
  773.     bne.s    decodem
  774.     move.b    2(pseudopc),d1
  775.     lsl.w    #8,d1
  776.     move.b    1(pseudopc),d1
  777.     cmpi.b    #$ED,(pseudopc) ;Is this an ED-prefix instruction?
  778.     beq.s    1$        ;Yes - the value is shifted one byte.
  779.     tst.b    prefix        ;DD or FD prefix?
  780.     beq.s    2$        ;No - we have the value.
  781. 1$    move.b    3(pseudopc),d1    ;The value is actually here.
  782.     lsl.w    #8,d1
  783.     move.b    2(pseudopc),d1
  784. 2$    bsr    uword        ;Convert the value to a hex string.
  785.     bra.s    decodex
  786. * Not a special code - just move the character as is.
  787. decodem move.b    (a1),(a0)+
  788. * Try for another character to move (and possibly decode).
  789. decodex addq.l    #1,a1
  790.     cmpi.b    #'$',(a1)
  791.     bne    decode
  792. *
  793. * Display the decoded instruction.
  794. *
  795. dispop    move.b    #cr,(a0)+
  796.     move.b    #lf,(a0)+
  797.     move.b    #'$',(a0)+
  798.     move.l    #workbuf,d1
  799.     bsr    pstring     ;Displaying as a single string is much faster.
  800. * Pause after every screenful to give the operator time to read it.
  801.     addq.b    #1,dumpcnt    ;Count the number of times dumped.
  802.     cmpi.b    #8,dumpcnt    ;Is the screen full of dumps?
  803.     bcs    dumpx        ;No - exit.
  804.     move.l    #dmpmsg3,d1
  805.     bsr    pstring     ;Ask for operator action.
  806.     bsr    dmpstr        ;Make sure the prompt gets out!
  807.     movem.l a0-a1/a6,-(sp)
  808.     move.l    rawhand,d1    ;Console input
  809.     move.l    #dumpcnt,d2
  810.     move.l    _DOSBase,a6
  811.     moveq    #1,d3
  812.     sys    Read        ;Get the operator's reply.
  813.     movem.l (sp)+,a0-a1/a6
  814.     bsr    pcrlf
  815.     cmpi.b    #'Q',dumpcnt    ;Does he want to quit?
  816.     beq    quitprg     ;Yes.
  817.     cmpi.b    #'q',dumpcnt
  818.     beq    quitprg
  819.     cmpi.b    #'S',dumpcnt    ;Stop tracing?
  820.     beq.s    2$        ;Yes.
  821.     cmpi.b    #'s',dumpcnt
  822.     beq.s    2$
  823.     cmpi.b    #'C',dumpcnt    ;Change trace address?
  824.     beq.s    1$        ;Yes.
  825.     cmpi.b    #'c',dumpcnt
  826.     bne.s    dmpcont
  827. 1$    bsr    gtrange        ;Get new trace range.
  828. 2$    clr.b    traceflg    ;Disable tracing and continue.
  829. dmpcont    clr.b    dumpcnt     ;Reset the dump counter.
  830. dumpx    movem.l (sp)+,d0-d3/a1
  831.     rts
  832.  
  833. dmpmsg3 dc.b    'Q to quit, S to stop tracing, C to change trace,'
  834.     dc.b    ' any other key to continue: $'
  835.  
  836. *
  837. * Display the register number indicated by the low-order 3 bits of D0.
  838. *  H and L will be displayed as XH and XL if necessary.
  839. *  M ((HL) for Z-80) will be converted to (IX+d) or (IY+d) if necessary.  
  840. *
  841. dspreg    andi.b    #7,d0        ;Isolate register number.
  842.     cmpi.b    #6,d0        ;Which register is it?
  843.     beq.s    dspregm     ;M - might need a special routine.
  844.     bhi.s    dsprega     ;A - this one is easy.
  845.     addi.b    #'B',d0     ;Registers B, C, D, E, H, and L
  846.     cmpi.b    #'F',d0     ;Is it H or L?
  847.     bcs.s    dspregb     ;No - we're ready.
  848.     bne.s    dspregl     ;It's L.
  849.     moveq    #'H',d0     ;It's H.
  850.     bra.s    dspregp
  851. dspregl moveq    #'L',d0     ;It's L.
  852. dspregp cmpi.b    #$DD,prefix    ;Are we manipulating an index register?
  853.     bcs.s    dspregb     ;No.
  854.     bne.s    dspregy     ;Register YH or YL
  855.     move.b    #'X',(a0)+    ;Register XH or XL
  856.     bra.s    dspregb
  857. dspregy move.b    #'Y',(a0)+
  858. dspregb move.b    d0,(a0)+
  859.     rts
  860. dsprega move.b    #'A',(a0)+    ;It's the accumulator.
  861.     rts
  862. dspregm cmpi.b    #$DD,prefix    ;Index register?
  863.     bcc.s    dspregi     ;Yes.
  864.     tst.b    z80flag     ;Are we using 8080 mnemonics?
  865.     bne.s    dspregz     ;No.
  866.     move.b    #'M',(a0)+    ;It's M for 8080.
  867.     rts
  868. dspregz move.b    #'(',(a0)+    ;It's (HL) for Z-80.
  869.     move.b    #'H',(a0)+
  870.     move.b    #'L',(a0)+
  871.     move.b    #')',(a0)+
  872.     rts
  873. dspregi move.b    #'(',(a0)+    ;It's an indexed operand.
  874.     move.b    #'I',(a0)+
  875.     move.b    #'X',(a0)+    ;Assume it's IX.
  876.     cmpi.b    #$DD,prefix    ;Is it?
  877.     beq.s    dspregd     ;Yes.
  878.     move.b    #'Y',-1(a0)    ;It's IY.
  879. dspregd move.b    #'+',(a0)+
  880.     move.b    2(pseudopc),d1    ;Displacement
  881.     bsr    ubyte
  882.     move.b    #')',(a0)+
  883.     rts
  884.  
  885. *
  886. * Display the contents of the flag register in D0.
  887. *
  888. dspflag    lea    workbuf,a0
  889.     move.b    #'-',d1        ;Carry (assume not set)
  890.     btst    #0,d0
  891.     beq    1$
  892.     move.b    #'C',d1        ;Carry flag is set.
  893. 1$    move.b    d1,(a0)+
  894.     move.b    #'-',d1        ;Zero
  895.     btst    #6,d0
  896.     beq    2$
  897.     move.b    #'Z',d1
  898. 2$    move.b    d1,(a0)+
  899.     move.b    #'-',d1        ;Minus
  900.     btst    #7,d0
  901.     beq    3$
  902.     move.b    #'M',d1
  903. 3$    move.b    d1,(a0)+
  904.     move.b    #'-',d1        ;Even parity
  905.     btst    #2,d0
  906.     beq    4$
  907.     move.b    #'E',d1
  908. 4$    move.b    d1,(a0)+
  909.     move.b    #'-',d1        ;Intermediate carry
  910.     btst    #4,d0
  911.     beq    5$
  912.     move.b    #'I',d1
  913. 5$    move.b    d1,(a0)+
  914.     move.b    #' ',(a0)+
  915.     rts
  916.     page
  917. *************************************************************************
  918. *                                    *
  919. *    Initialization subroutines                    *
  920. *                                    *
  921. *************************************************************************
  922.  
  923. *
  924. * Load up the fake FDOS.
  925. *
  926. lodfdos move.l    a6,-(sp)
  927.     lea    fdos,a6
  928.     move.l    targbase,pseudosp
  929.     adda.l    #$10000,pseudosp
  930.     lea    -256(pseudosp),a0
  931.     move.w    #fdoslen,d0
  932. 1$    move.b    (a6)+,(a0)+
  933.     dbra    d0,1$
  934.     lea    -256(pseudosp),a0
  935.     move.l    a0,d0
  936.     sub.l    targbase,d0
  937.     move.b    #tJMP,0(targbase)    ;Build BIOS and BDOS jumps.
  938.     move.b    #tJMP,5(targbase)
  939.     move.b    d0,6(targbase)
  940.     rol.w    #8,d0
  941.     move.b    d0,7(targbase)
  942.     rol.w    #8,d0
  943.     addq.w    #3,d0
  944.     move.b    d0,1(targbase)
  945.     rol.w    #8,d0
  946.     move.b    d0,2(targbase)
  947.     clr.w    -(pseudosp)    ;Set up a return stack to exit simulation.
  948.     move.l    (sp)+,a6
  949.     rts
  950.  
  951. *
  952. * Set up working registers.
  953. *
  954. lodregs lea    optabl,opptr    ;Point base reg. to opcode dispatch table.
  955.     lea    mloop,return
  956.     tst.b    traceit     ;Is tracing required?
  957.     beq.s    1$        ;No.
  958.     lea    mloopt,return    ;Point return to trace test.
  959. 1$    lea    flags,flagptr
  960.     lea    $100(targbase),pseudopc ;Start execution at 0100H.
  961.     moveq    #$E,regcon0e        ;Set up quick constants.
  962.     moveq    #$1,regcon01
  963.     moveq    #$F,regcon0f
  964.     move.l    #$FF,regconff
  965.     moveq    #0,rega
  966.     moveq    #0,regf
  967.     clr.b    regi(regs)
  968.     rts
  969.     page
  970. *
  971. * Get start and end addresses for tracing.
  972. *
  973. entrads tst.b    traceit     ;Is tracing required?
  974.     beq    entradx     ;No.
  975.     bsr    gtrange     ;Get trace range.
  976. * Find out whether BIOS/BDOS calls are to be traced.
  977.     move.l    #btrcmsg,d1
  978.     bsr    pstring
  979.     lea    workbuf,a0
  980.     move.b    #10,(a0)
  981.     bsr    getline
  982.     move.b    #1,btrcflg
  983.     cmpi.b    #'Y',workbuf+2
  984.     beq.s    entradx
  985.     cmpi.b    #'y',workbuf+2
  986.     beq.s    entradx
  987.     clr.b    btrcflg
  988. entradx clr.b    traceflg    ;Start with tracing turned off.
  989.     rts
  990.  
  991. gtrange move.l    #tracemsg,d1    ;Enter trace address if necessary.
  992.     bsr    pstring
  993.     lea    workbuf,a0
  994.     move.b    #workbufn-workbuf-2,(a0)
  995.     bsr    getline     ;Get the string.
  996.     moveq    #0,d0
  997.     move.b    1(a0),d0    ;Number of bytes read
  998.     addq.l    #2,a0        ;Skip over length information.
  999.     clr.b    0(a0,d0)    ;Insert string terminator.
  1000.     bsr    atol        ;Get trace start address.
  1001.     andi.l    #$FFFF,d1
  1002.     add.l    #target,d1
  1003.     move.l    d1,tracesad
  1004. * Now get the ending address.
  1005.     move.l    #tracemg2,d1
  1006.     bsr    pstring
  1007.     lea    workbuf,a0
  1008.     move.b    #workbufn-workbuf-2,(a0)
  1009.     bsr    getline
  1010.     moveq    #0,d0
  1011.     move.b    1(a0),d0
  1012.     addq.l    #2,a0
  1013.     clr.b    0(a0,d0)
  1014.     bsr    atol
  1015.     andi.l    #$FFFF,d1
  1016.     add.l    #target,d1
  1017.     move.l    d1,traceead
  1018.     bsr    pcrlf
  1019.     rts
  1020.  
  1021. tracemsg dc.b    cr,lf,'Start trace at >$'
  1022. tracemg2 dc.b    '  End trace at >$'
  1023. btrcmsg dc.b    'Trace BIOS/BDOS calls? >$'
  1024.  
  1025. *
  1026. * Open the file to be loaded, and load it into target space if successful.
  1027. *
  1028. loadcom movem.l d1-d3/a1-a2/a6,-(sp)    ;Save registers.
  1029.     lea    cmdline,a0
  1030.     tst.b    cmdflag     ;Do we have a command already?
  1031.     bne.s    scancmd     ;Yes - process it.
  1032. * Display the command prompt.
  1033. prompt    lea    target,targbase ;Just in case "targbase" gets clobbered
  1034.     move.b    4(targbase),d1    ;Get the default drive code.
  1035.     andi.b    #$0F,d1
  1036.     addi.b    #'A',d1     ;Convert drive code to ASCII letter.
  1037.     bsr    pchar        ;Display the current drive.
  1038.     move.b    4(targbase),d1    ;Get user number.
  1039.     lsr.b    #4,d1        ;Move it to low-order 4 bits.
  1040.     beq.s    promptp     ;Don't insert user number if it's zero.
  1041.     cmpi.b    #10,d1        ;Is user number 10 or greater?
  1042.     bcs.s    promptu     ;No.
  1043.     move.b    d1,-(sp)
  1044.     move.b    #'1',d1
  1045.     bsr    pchar        ;Display tens digit of user number.
  1046.     move.b    (sp)+,d1
  1047.     subi.b    #10,d1
  1048. promptu addi.b    #'0',d1     ;Convert user number to ASCII.
  1049.     bsr    pchar        ;Display user number.
  1050. promptp move.b    #'>',d1
  1051.     bsr    pchar
  1052.     lea    cmdline,a0
  1053.     move.b    #cmdlinen-cmdline-2,(a0)
  1054.     bsr    getline     ;Get a command line.
  1055.     moveq    #0,d0
  1056.     move.b    1(a0),d0    ;Length of command line
  1057.     beq.s    prompt        ;Zero - try again.
  1058.     addq.l    #2,a0        ;Skip over length information.
  1059.     clr.b    0(a0,d0)    ;Insert command line terminator.
  1060.     cmpi.b    #3,(a0)     ;Control-C?
  1061.     bne.s    scancmd     ;No.
  1062.     move.b    #1,quitflg    ;Set quit flag.
  1063.     bra    quitprg     ;Exit the simulator.
  1064. scancmd clr.b    cmdflag     ;Ask for a new command next time.
  1065.     clr.b    builtin     ;Clear "built-in command" flag.
  1066. * Check for a change of drive number.
  1067.     tst.b    2(a0)        ;Is the command two characters long?
  1068.     bne.s    convcmd     ;No - treat as a normal command.
  1069.     cmpi.b    #':',1(a0)    ;Drive specifier?
  1070.     bne.s    convcmd     ;No.
  1071.     bsr    ucase        ;Get the drive code.
  1072.     cmpi.b    #'A',d0     ;Is it valid?
  1073.     bcs.s    opensel     ;No.
  1074.     cmpi.b    #'P',d0
  1075.     bhi.s    opensel
  1076.     subq.b    #1,d0
  1077.     andi.b    #$0F,d0     ;New drive code
  1078.     andi.b    #$F0,4(targbase)
  1079.     or.b    d0,4(targbase)    ;Insert into current drive slot.
  1080.     bra    prompt
  1081. opensel move.l    #1$,d1
  1082.     bsr    pstring     ;'BDOS Error on '
  1083.     bsr    ucase
  1084.     move.b    d0,d1
  1085.     bsr    pchar        ;Drive letter
  1086.     move.l    #2$,d1
  1087.     bsr    pstring     ;': Select'
  1088.     bra    prompt        ;Try again.
  1089.  
  1090. 1$    dc.b    'BDOS Error on $'
  1091. 2$    dc.b    ': Select',cr,lf,'$'
  1092.  
  1093. * Convert the program file name to an AmigaDOS file name in "comname".
  1094. convcmd lea    comname,a2
  1095.     cmpi.b    #':',1(a0)    ;Is there a drive specifier?
  1096.     bne.s    1$        ;No.
  1097.     bsr    ucase        ;Get the drive letter.
  1098.     cmpi.b    #'A',d0     ;Is it valid?
  1099.     bcs.s    opensel     ;No.
  1100.     cmpi.b    #'P',d0
  1101.     bhi.s    opensel
  1102.     addq.l    #1,a0        ;Skip over the colon.
  1103.     bra.s    2$
  1104. 1$    move.b    4(targbase),d0    ;Current drive and user number
  1105.     beq.s    loadnam     ;Drive A:, user 0
  1106.     andi.b    #$0F,d0     ;Isolate current drive bits
  1107.     addi.b    #'A',d0     ;Convert to drive code.
  1108. 2$    move.b    4(targbase),d1    ;Current drive and user number
  1109.     lsr.b    #4,d1        ;Isolate the user number.
  1110.     bne.s    3$        ;Not zero - make a directory name.
  1111.     cmpi.b    #'A',d0     ;Are we loading from drive A:?
  1112.     beq.s    loadnam     ;Yes - use the current directory.
  1113. 3$    move.b    #'C',(a2)+    ;Convert to AmigaDOS device.
  1114.     move.b    #'P',(a2)+
  1115.     move.b    #'M',(a2)+
  1116.     move.b    d0,(a2)+    ;Insert the drive letter.
  1117.     tst.b    d1        ;User zero?
  1118.     beq.s    5$        ;Yes - don't bother inserting it.
  1119.     move.b    #'0',(a2)+    ;Assume user number is less than 10.
  1120.     cmpi.b    #10,d1        ;Is user number 10 or greater?
  1121.     bcs.s    4$        ;No.
  1122.     move.b    #'1',-1(a2)    ;Change the first digit to 1.
  1123.     subi.b    #10,d1
  1124. 4$    addi.b    #'0',d1     ;Convert user number to ASCII.
  1125.     move.b    d1,(a2)+    ;Insert user number into file spec.
  1126. 5$    move.b    #':',(a2)+    ;Insert a colon.
  1127. loadnam move.l    #comnamen,d1    ;End of name, allowing for .COM suffix
  1128.     subq.l    #6,d1        ;Allow for .COM suffix.
  1129.     sub.l    a2,d1        ;Adjust for directory prefix, if any.
  1130. 1$    bsr    ucase        ;Convert file name to upper case.
  1131.     move.b    d0,(a2)+
  1132.     cmpi.b    #' ',(a0)    ;End of name?
  1133.     beq.s    gotname     ;Yes.
  1134.     tst.b    (a0)        ;End of command string?
  1135.     dbeq    d1,1$        ;No - keep on going.
  1136. gotname move.l    a0,comend    ;Save position in command line.
  1137.     move.b    #'.',(a2)+    ;Mash file name to .COM.
  1138.     move.b    #'C',(a2)+
  1139.     move.b    #'O',(a2)+
  1140.     move.b    #'M',(a2)+
  1141.     clr.b    (a2)
  1142.     clr.b    cmdline     ;Ask for a new command next time.
  1143. * If this is a USER or SAVE command, don't look for a .COM file -
  1144. *  we'll process these commands ourselves.
  1145.     lea    comname,a0    ;Scan for possible device name.
  1146.     move.l    a0,a1        ;Use A1 as a scan pointer - preserve A0.
  1147. 1$    tst.b    (a1)        ;End of command name?
  1148.     beq.s    2$        ;Yes - there is no device name.
  1149.     cmpi.b    #':',(a1)+    ;End of device name?
  1150.     bne.s    1$        ;No - continue scanning.
  1151.     move.l    a1,a0        ;Point A0 past the device name.
  1152. 2$    cmpi.b    #'.',4(a0)    ;Is the command name four characters long?
  1153.     bne    opencom     ;No.
  1154.     cmpi.b    #'U',(a0)    ;Check for a USER command.
  1155.     bne.s    tstsave
  1156.     cmpi.b    #'S',1(a0)
  1157.     bne.s    tstsave
  1158.     cmpi.b    #'E',2(a0)
  1159.     bne.s    tstsave
  1160.     cmpi.b    #'R',3(a0)
  1161.     bne.s    tstsave
  1162.     move.b    #1,builtin    ;Indicate we have a USER command.
  1163.     bra    loaded
  1164. tstsave cmpi.b    #'S',(a0)    ;Check for a SAVE command.
  1165.     bne.s    opencom
  1166.     cmpi.b    #'A',1(a0)
  1167.     bne.s    opencom
  1168.     cmpi.b    #'V',2(a0)
  1169.     bne.s    opencom
  1170.     cmpi.b    #'E',3(a0)
  1171.     bne.s    opencom
  1172.     move.b    #2,builtin    ;Indicate we have a SAVE command.
  1173.     bra    loaded
  1174. * Open the command file and load it if it exists.
  1175. opencom move.l    #comname,d1
  1176.     move.l    #MODE_OLDFILE,d2
  1177.     move.l    _DOSBase,a6
  1178.     sys    Open        ;Open the file.
  1179.     tst.l    d0        ;Did the open fail?
  1180.     bne.s    comopen     ;No.
  1181.     lea    comname,a0
  1182. openerr cmpi.b    #'.',(a0)+    ;Find end of file name.
  1183.     bne.s    openerr
  1184.     move.b    #'?',-1(a0)
  1185.     move.b    #cr,(a0)+
  1186.     move.b    #lf,(a0)+
  1187.     move.b    #'$',(a0)
  1188.     move.l    #comname,d1
  1189.     bsr    pstring     ;Echo "name?"
  1190.     bra    prompt        ;Try again.
  1191.  
  1192. comopen move.l    d0,-(sp)    ;Save the file handle.
  1193.     move.l    d0,d1
  1194.     move.l    pseudopc,d2    ;Start loading at $0100 in target.
  1195.     move.l    #65536-512,d3    ;Maximum number of bytes to load
  1196.     move.l    _DOSBase,a6
  1197.     sys    Read        ;Load the .COM file.
  1198.     move.l    (sp)+,d1
  1199.     move.l    _DOSBase,a6
  1200.     sys    Close        ;Close the .COM file.
  1201.  
  1202. * The program has now been loaded (unless it's USER or SAVE).
  1203. loaded    movem.l (sp)+,d1-d3/a1-a2/a6    ;Refresh registers.
  1204.     movem.l d1-d3/a1-a2/a6,-(sp)
  1205.     lea    $80(targbase),a0    ;Set up target's base page.
  1206.     move.l    a0,dmaaddr
  1207.  
  1208. * Set up FCBs and command line tail.
  1209.     lea    $5C(targbase),a0
  1210.     lea    $6C(targbase),a2
  1211.     clr.b    (a0)+
  1212.     clr.b    (a2)+
  1213.     moveq    #10,d0
  1214. clrfcb    move.b    #' ',(a0)+    ;Clear FCBs.
  1215.     move.b    #' ',(a2)+
  1216.     dbra    d0,clrfcb
  1217.     clr.b    $80(targbase)    ;Clear the command line tail.
  1218.  
  1219.     move.l    comend,a0    ;Restore position in command line.
  1220. fcb1    tst.b    (a0)        ;End of command line?
  1221.     beq    loadusr     ;Yes.
  1222.     cmpi.b    #' ',(a0)+    ;Skip over to first file name
  1223.     beq.s    fcb1
  1224.     subq.l    #1,a0        ;Back onto start of file name.
  1225.     move.l    a0,-(sp)    ;Save position on command line.
  1226.     lea    $81(targbase),a2;A2 loads the command line tail.
  1227. gettail move.b    (a0)+,(a2)+    ;Copy the command tail.
  1228.     bne.s    gettail
  1229.     move.l    a2,d0
  1230.     lea    $82(targbase),a0;Don't count null terminator!
  1231.     sub.l    a0,d0
  1232.     move.b    d0,$80(targbase);Length of command line tail
  1233.     move.l    (sp)+,a0    ;Go back to the first file name.
  1234.  
  1235.     lea    $5C(targbase),a2;Address of current FCB
  1236. getfcb    move.l    a2,fcbptr    ;Save pointer to current FCB.
  1237.     cmpi.b    #':',1(a0)    ;Is a drive specified?
  1238.     bne.s    1$        ;No.
  1239.     move.b    (a0),(a2)    ;Get drive letter.
  1240.     subi.b    #'A'-1,(a2)    ;Convert to drive code.
  1241.     addq.l    #2,a0        ;Skip over drive designator.
  1242.     tst.b    (a0)        ;End of command line?
  1243.     beq.s    loadusr     ;Yes - we're done.
  1244.     cmpi.b    #' ',(a0)    ;End of file name?
  1245.     beq.s    getfcbx     ;Yes.
  1246. 1$    addq.l    #1,a2        ;Start of file name in FCB
  1247. 2$    move.b    (a0)+,(a2)+    ;Copy file name to FCB.
  1248. 3$    tst.b    (a0)        ;End of command?
  1249.     beq.s    loadusr     ;Yes.
  1250.     cmpi.b    #' ',(a0)    ;End of file name?
  1251.     beq.s    getfcbx     ;Yes.
  1252.     cmpi.b    #'.',(a0)    ;Start of file name extension?
  1253.     bne.s    2$        ;No - continue loading file name.
  1254.     move.l    fcbptr,a2    ;Copy original pointer
  1255.     lea    9(a2),a2    ;Skip over to extension field.
  1256.     addq.l    #1,a0        ;Skip over the period.
  1257.     bra.s    3$
  1258. getfcbx tst.b    (a0)        ;End of command line?
  1259.     beq.s    loadusr     ;Yes.
  1260.     cmpi.b    #' ',(a0)+    ;Look for another file name.
  1261.     beq.s    getfcbx
  1262.     subq.l    #1,a0        ;Back onto start of file name.
  1263.     move.l    fcbptr,d0
  1264.     lea    $5C(targbase),a2
  1265.     cmp.l    d0,a2        ;Was this the first FCB?
  1266.     bne.s    loadusr     ;No - stop after two FCBs.
  1267.     lea    16(a2),a2    ;Skip over to the next FCB.
  1268.     bra.s    getfcb        ;Load the next FCB.
  1269.  
  1270. * If this is a USER or SAVE command, process it here.
  1271. *  These are the only built-in commands that SimCPM supports,
  1272. *  since the rest are just as easily done through the CLI.
  1273. *  The first operand is a USER number or the number of pages to SAVE.
  1274. loadusr tst.b    builtin     ;Is this a built-in command?
  1275.     beq    loadcmx     ;No - we're done.
  1276.     lea    $5C(targbase),a0 ;Scan the first FCB.
  1277.     moveq    #0,d0        ;Build the number here.
  1278.     tst.b    (a0)+        ;Is drive code omitted?
  1279.     bne.s    badunum     ;No - we don't have a valid number.
  1280.     cmpi.b    #' ',(a0)    ;Is the number missing?
  1281.     beq.s    badunum     ;Yes - error.
  1282.     cmpi.b    #' ',3(a0)    ;Is the number too long?
  1283.     bne.s    badunum     ;Yes - it's likely too big.
  1284. getuser cmpi.b    #'0',(a0)    ;Is the current digit valid?
  1285.     bcs.s    badunum     ;No.
  1286.     cmpi.b    #'9',(a0)
  1287.     bhi.s    badunum
  1288.     mulu    #10,d0        ;Shift previous digits, if any.
  1289.     move.b    (a0)+,d1    ;Get the current digit.
  1290.     andi.w    #$0F,d1     ;Convert current digit to binary.
  1291.     add.w    d1,d0        ;Accumulate total.
  1292.     cmpi.b    #' ',(a0)    ;End of number?
  1293.     bne.s    getuser     ;No - try for another digit.
  1294.     bra.s    chkuser
  1295. badunum moveq    #-1,d0        ;Invalid number
  1296. chkuser cmpi.b    #1,builtin    ;Is this a USER command?
  1297.     bne.s    chksave     ;No.
  1298.     cmpi.w    #15,d0        ;Is user number over 15?
  1299.     bls.s    setuser     ;No - it's valid.
  1300.     move.l    #badumsg,d1
  1301.     bsr    pstring     ;Display an error message and try again.
  1302.     bra    prompt
  1303. setuser andi.b    #$0F,4(targbase);Clear original user number.
  1304.     lsl.b    #4,d0        ;Move new user bits into position.
  1305.     or.b    d0,4(targbase)    ;Insert new user number.
  1306.     bra    prompt
  1307.  
  1308. badumsg dc.b    'Invalid user number',cr,lf,'$'
  1309.  
  1310. chksave tst.w    d0        ;Attempt to save zero blocks?
  1311.     beq.s    badblks     ;Yes - error.
  1312.     cmpi.w    #255,d0     ;Is number of blocks to SAVE valid?
  1313.     bls.s    savefn        ;Yes.
  1314. badblks move.l    #1$,d1
  1315.     bsr    pstring
  1316.     bra    prompt
  1317. 1$    dc.b    'Number of pages must be from 1 to 255.',cr,lf,'$'
  1318. savefn    lea    $6C(targbase),a0;FCB for SAVE file name
  1319.     cmpi.b    #' ',1(a0)    ;Is file name missing?
  1320.     bne.s    opensav     ;No.
  1321.     move.l    #1$,d1
  1322.     bsr    pstring
  1323.     bra    prompt
  1324. 1$    dc.b    'File name is missing.',cr,lf,'$'
  1325. opensav lea    opnname,a1    ;Build AmigaDOS file name here.
  1326.     move.l    a1,d1        ;We'll need it here.
  1327.     move.l    d0,-(sp)    ;Save number of blocks to save.
  1328.     bsr    convfn        ;Make a file name.
  1329.     move.l    #MODE_NEWFILE,d2
  1330.     move.l    _DOSBase,a6
  1331.     sys    Open        ;Open the file.
  1332.     tst.l    d0        ;Did the open fail?
  1333.     bne.s    saveit        ;No.
  1334.     move.l    (sp)+,d0    ;Clean up the stack.
  1335.     move.l    #1$,d1
  1336.     bsr    pstring
  1337.     bra    prompt
  1338. 1$    dc.b    'Unable to open file for SAVE.',cr,lf,'$'
  1339. saveit    move.l    d0,d1        ;Handle for SAVE file
  1340.     lea    target+$100,a0    ;"targbase" isn't intact right now.
  1341.     move.l    a0,d2        ;Start of data to save
  1342.     move.l    (sp)+,d3    ;Number of 256-byte pages to save
  1343.     asl.l    #8,d3        ;Convert to number of bytes.
  1344.     move.l    d1,-(sp)    ;Save the file handle.
  1345.     sys    Write        ;Write the file.
  1346.     move.l    (sp)+,d1
  1347.     sys    Close        ;Close the file.
  1348.     bra    prompt        ;Successful completion
  1349.  
  1350. * We have successfully loaded a .COM file.
  1351. loadcmx movem.l (sp)+,d1-d3/a1-a2/a6    ;Restore registers.
  1352.     rts            ;Exit.
  1353.  
  1354. *
  1355. * Subroutine to get a character and convert it to upper case
  1356. *
  1357. ucase    move.b    (a0)+,d0
  1358.     cmpi.b    #'a',d0
  1359.     bcs.s    ucasex
  1360.     cmpi.b    #'z',d0
  1361.     bhi.s    ucasex
  1362.     subi.b    #'a'-'A',d0
  1363. ucasex    rts
  1364.     page
  1365. *************************************************************************
  1366. *                                    *
  1367. *    BDOS / BIOS service routines                    *
  1368. *                                    *
  1369. *************************************************************************
  1370. service movem.l a1/a6,-(sp)
  1371.     move.b    rega,newrega    ;Save Z-80 accumulator (D2)
  1372.     move.l    _DOSBase,a6    ;Get dos.library pointer
  1373. * Decode the byte following the HLT instruction (BIOS call type).
  1374.     moveq    #0,d0        ;Handle BIOS/BDOS service request
  1375.     move.b    (pseudopc)+,d0    ; of form HLT DB opcode.
  1376.     cmp    #(biostabn-biostab)/4,d0
  1377.     blt.s    dobios        ;Function number is within range.
  1378. badbios move.b    d0,-(sp)    ;Flag illegal BIOS call
  1379.     move.l    #ilgbios,d1    ; and spill guts.
  1380.     bsr    pstring
  1381.     move.b    (sp)+,d1
  1382.     bsr    pbyte
  1383.     move.l    #atmsg,d1
  1384.     bsr    pstring
  1385.     move.b    1(pseudosp),d1    ;Address where called (top stack entry)
  1386.     ror.w    #8,d1
  1387.     move.b    0(pseudosp),d1
  1388.     bsr    pword
  1389.     bsr    pcrlf
  1390.     bsr    dump
  1391.     bra    quitprg
  1392.  
  1393. ilgbios dc.b    cr,lf,'Illegal BIOS call $'
  1394. biosmsg dc.b    'BIOS call $'
  1395. atmsg    dc.b    ' (hex) at $'
  1396.  
  1397. dobios    move.l    d0,-(sp)    ;Save BIOS function number.
  1398.     beq.s    biostrx     ;Zero - it's a BDOS call.
  1399.     tst.b    btrcflg     ;Trace BIOS calls?
  1400.     beq.s    biostrx     ;No.
  1401.     move.l    #biosmsg,d1
  1402.     bsr    pstring
  1403.     move.l    (sp),d1
  1404.     bsr    pbyte
  1405.     move.l    #atmsg,d1
  1406.     bsr    pstring
  1407.     move.b    1(pseudosp),d1    ;Address where called (top stack entry)
  1408.     ror.w    #8,d1
  1409.     move.b    0(pseudosp),d1
  1410.     bsr    pword
  1411.     bsr    pcrlf
  1412.     move.l    (sp),d0
  1413. biostrx asl    #2,d0        ;Multiply function number by 4.
  1414.     addi.l    #biostab,d0    ;Point at address table entry.
  1415.     movea.l d0,a0
  1416.     movea.l (a0),a0     ;Point to appropriate service routine.
  1417.     move.l    (sp)+,d0    ;Restore BIOS function number.
  1418.     jmp    (a0)        ;Jump to the routine.
  1419. * If the BIOS code is zero, it's a BDOS call.
  1420. *  Decode register C using a similar routine to the BIOS decoding above.
  1421. bdosfn    moveq    #0,d0
  1422.     move.b    regc(regs),d0    ;Get BDOS function number.
  1423.     cmp    #(bdostabn-bdostab)/4,d0
  1424.     blt.s    dobdos        ;Function number is within range.
  1425. badbdos move.b    d0,-(sp)
  1426.     move.l    #ilgbdos,d1    ;Illegal or unsupported BDOS call
  1427.     bsr    pstring
  1428.     move.b    (sp)+,d1
  1429.     bsr    pbyte
  1430.     move.l    #atmsg,d1
  1431.     bsr    pstring
  1432.     move.b    1(pseudosp),d1    ;Address where called (top stack entry)
  1433.     ror.w    #8,d1
  1434.     move.b    0(pseudosp),d1
  1435.     bsr    pword
  1436.     bsr    pcrlf
  1437.     bsr    dump
  1438.     bra    quitprg
  1439.  
  1440. ilgbdos dc.b    cr,lf,'Illegal BDOS call $'
  1441. bdosmsg dc.b    'BDOS call $'
  1442.  
  1443. dobdos    move.l    d0,-(sp)    ;Save BDOS function number.
  1444.     tst.b    btrcflg     ;Trace BDOS calls?
  1445.     beq.s    bdostrx     ;No.
  1446.     move.l    #bdosmsg,d1
  1447.     bsr    pstring
  1448.     move.l    (sp),d1
  1449.     bsr    pbyte
  1450.     move.l    #atmsg,d1
  1451.     bsr    pstring
  1452.     move.b    1(pseudosp),d1
  1453.     ror.w    #8,d1
  1454.     move.b    0(pseudosp),d1
  1455.     bsr    pword
  1456.     bsr    pcrlf
  1457.     move.l    (sp),d0
  1458. bdostrx cmpi.b    #10,d0        ;BDOS function 10 or higher?
  1459.     bcs.s    bdosjmp     ;No.
  1460.     bsr    dmpstr        ;Dump any outstanding console output.
  1461.     move.l    (sp),d0     ;Restore BDOS function number.
  1462. bdosjmp asl    #2,d0        ;Multiply function number by 4.
  1463.     addi.l    #bdostab,d0    ;Point at address table entry.
  1464.     movea.l d0,a0
  1465.     movea.l (a0),a0     ;Point to appropriate service routine.
  1466.     move.l    (sp)+,d0    ;Restore BDOS function number.
  1467.     moveq    #0,d1
  1468.     move.w    regd(regs),d1    ;Get argument.
  1469.     jmp    (a0)        ;Jump to the routine.
  1470. * Return here after performing the BDOS function.
  1471. results movem.l (sp)+,a1/a6
  1472.     moveq    #0,rega
  1473.     move.b    newrega,rega    ;Get new accumulator value.
  1474. * We have finished processing the BDOS function.
  1475.     move.b    rega,d0     ;Set flags.
  1476.     and.w    regconff,d0
  1477.     move.b    0(flagptr,d0.w),regf
  1478.     rts
  1479. *
  1480. * Individual BDOS service routines
  1481. *
  1482. bdos00    bra    quitprg     ;Exit program.
  1483.  
  1484. bdos01    bsr    dmpstr        ;Console input
  1485.     move.l    rawhand,d1
  1486.     move.l    #newrega,d2
  1487.     moveq    #1,d3
  1488.     sys    Read
  1489.     bra    results
  1490.  
  1491. bdos02    move.b    rege(regs),d1    ;Console output
  1492.     clr.b    testdol     ;Allow dollar signs
  1493.     bsr    pchar
  1494.     bra    results
  1495.  
  1496. bdos03    equ    badbdos     ;Reader input
  1497.  
  1498. bdos04    equ    badbdos     ;Punch output
  1499.  
  1500. bdos05    pea    rege(regs)    ;List output byte
  1501. bdos05t tst.b    listopn     ;Is the printer already open?
  1502.     bne.s    bdos05w     ;Yes.
  1503.     move.l    #prtname,d1
  1504.     move.l    #MODE_NEWFILE,d2
  1505.     sys    Open        ;Open the printer.
  1506.     move.l    d0,prthand    ;Save the file handle.
  1507.     bne.s    1$        ;The open was successful.
  1508.     move.l    #badprt,d1
  1509.     bsr    pstring     ;Indicate an unsuccessful open.
  1510.     bsr    dump        ;Spill guts...
  1511.     bra    quitprg     ; and exit.
  1512. 1$    move.b    #1,listopn    ;Indicate that the list device is open.
  1513. bdos05w move.l    prthand,d1
  1514.     move.l    (sp)+,d2    ;Character to send to the list device
  1515.     moveq    #1,d3        ;Just send one byte.
  1516.     sys    Write        ;Send the byte to the list device.
  1517.     bra    results
  1518.     
  1519. prtname dc.b    'PRT:RAW',0
  1520. badprt    dc.b    'Unable to open the list device!$'
  1521.  
  1522. bdos06    cmpi.b    #$FF,rege(regs) ;Direct console I/O
  1523.     bne    bdos02        ;Send the byte.
  1524.     bsr    dmpstr        ;Dump any outstanding output.
  1525.     move.l    rawhand,d1
  1526.     moveq    #1,d2        ;Wait for one microsecond.
  1527.     sys    WaitForChar    ;Check whether a character is ready.
  1528.     tst.l    d0        ;Is a character ready?
  1529.     bne    bdos01        ;Yes - get it.
  1530.     clr.b    newrega     ;Indicate that nothing is ready.
  1531.     bra    results
  1532.  
  1533. bdos07    move.b    3(targbase),newrega    ;Get IOBYTE
  1534.     bra    results
  1535.  
  1536. bdos08    move.b    rege(regs),3(targbase)    ;Set IOBYTE
  1537.     bra    results
  1538.  
  1539. bdos09    add.l    targbase,d1    ;Console output string
  1540.     bsr    pstring
  1541.     bra    results
  1542.  
  1543. bdos10    add.l    targbase,d1    ;Console input line
  1544.     movea.l d1,a0        ;The buffer is here.
  1545.     bsr    getline     ;Get a line.
  1546.     cmpi.b    #3,2(a0)    ;Was it a control-C?
  1547.     bne    results     ;No - continue processing.
  1548.     bra    quitprg     ;Terminate the program.
  1549.  
  1550. bdos11    move.l    rawhand,d1    ;Console status check
  1551.     moveq    #1,d2        ;Wait for one microsecond.
  1552.     sys    WaitForChar    ;Check whether a character is ready.
  1553.     move.b    d0,newrega    ;Result is compatible with CP/M.
  1554.     bra    results
  1555.  
  1556. bdos12    clr.b    regh(regs)    ;Get system identification
  1557.     move.b    #$22,regl(regs) ;Pretend we're CP/M 2.2.
  1558.     move.b    #$22,newrega    ;Some programs use undocumented return reg.
  1559.     clr.b    regb(regs)
  1560.     bra    results
  1561.  
  1562. bdos13    move.b    4(targbase),d0    ;Reset all drives
  1563.     andi.b    #$0F,d0     ;Current drive
  1564.     moveq    #1,d1
  1565.     lsl.w    d0,d1        ;Set up drive bit.
  1566.     move.w    d1,acmap    ;Set active drive map to current drive only.
  1567.     clr.w    romap        ;Reset read-only map.
  1568.     bra    results
  1569.  
  1570. bdos14    move.b    rege(regs),d0    ;Select drive
  1571.     andi.b    #$0F,d0     ;Isolate drive bits.
  1572.     andi.b    #$F0,4(targbase)
  1573.     or.b    d0,4(targbase)    ;Insert new bits.
  1574.     moveq    #1,d1
  1575.     lsl.w    d0,d1        ;Set up drive bit.
  1576.     or.w    d0,acmap    ;Add new drive to active drive map.
  1577.     bra    results
  1578.  
  1579. bdos15    move.l    d1,-(sp)    ;Open existing file
  1580.     bsr    gethand
  1581.     tst.l    d1        ;Is the file already open?
  1582.     beq.s    bdos15g        ;No - go ahead.
  1583.     clr.l    (a1)        ;Clear file handle table entry.
  1584.     sys    Close        ;Close the file.
  1585. bdos15g    move.l    (sp)+,d1
  1586.     add.l    #target,d1
  1587.     move.l    #MODE_OLDFILE,d2
  1588.     movea.l d1,a0        ;The FCB is here.
  1589.     bsr    mapdrv        ;Get drive map bit.
  1590. bdos15o move.l    a0,-(sp)
  1591.     lea    opnname,a1    ;Build AmigaDOS file name here.
  1592.     move.l    a1,d1        ;We'll need it here.
  1593.     bsr    convfn        ;Make a file name.
  1594.     sys    Open        ;Open the file.
  1595.     move.l    (sp)+,a1    ;The FCB is here.
  1596.     lea    handles,a0
  1597.     moveq    #(handlen-handles)/16-1,d1
  1598.     move.b    #$FF,newrega    ;Assume the open failed.
  1599.     tst.l    d0        ;Did it fail?
  1600.     beq    results        ;Yes.
  1601.     clr.b    newrega     ;Set flag to indicate success.
  1602. 1$    tst.l    (a0)        ;Available handle entry?
  1603.     beq.s    2$        ;Yes.
  1604.     lea    16(a0),a0    ;Check the next entry.
  1605.     dbra    d1,1$
  1606.     move.l    d0,d1        ;File handle table overflow!
  1607.     sys    Close        ;Close the file.
  1608.     move.l    #fullmsg,d1
  1609.     bsr    pstring     ;Display an error message
  1610.     bra    quitprg     ; and forget the whole thing.
  1611. 2$    move.l    d0,(a0)+    ;Save the file handle.
  1612.     moveq    #11,d0
  1613. 3$    move.b    (a1)+,(a0)+    ;Move first 12 bytes of FCB to table.
  1614.     dbra    d0,3$
  1615.     move.w    newdmap,d0
  1616.     or.w    d0,acmap    ;Add drive to active drive map.
  1617.     bra    results
  1618.  
  1619. fullmsg dc.b    'Too many files are open!',cr,lf,'$'
  1620.  
  1621. bdos16    move.b    #$FF,newrega    ;Close file
  1622.     bsr    gethand     ;Get the file handle.
  1623.     tst.l    d1        ;Did we find it?
  1624.     beq    results     ;No - return failure code.
  1625.     clr.l    (a1)        ;Clear the handle table entry.
  1626.     sys    Close        ;Close the file.
  1627.     clr.b    newrega     ;Indicate success.
  1628.     bra    results
  1629.  
  1630. bdos18    lea    renname,a0    ;Search for next file
  1631.     bra.s    bdos17i
  1632. bdos17    lea    srchnam,a0    ;Search for first file
  1633. bdos17i    move.b    #$FF,newrega    ;Assume we'll fail.
  1634.     add.l    targbase,d1
  1635.     movea.l d1,a1        ;The FCB is here.
  1636.     addq.l    #1,a1        ;The file name is here.
  1637.     moveq    #10,d0
  1638. 1$    cmp.b    #'*',(a1)    ;Is this an asterisk?
  1639.     beq.s    2$        ;Yes - replace with question marks.
  1640.     move.b    (a1)+,(a0)+    ;Move the current character.
  1641.     dbra    d0,1$
  1642.     bra.s    bdos17c
  1643. 2$    move.b    #'?',(a0)+    ;Convert to question marks.
  1644.     addq.l    #1,a1
  1645.     subq    #1,d0
  1646.     bmi.s    bdos17c        ;The asterisk was in the extension.
  1647.     cmpi.w    #2,d0        ;End of file name?
  1648.     bne.s    2$        ;No - insert another question mark.
  1649.     bra.s    1$        ;Start the extension field.
  1650. bdos17c    lea    target,targbase
  1651.     cmpi.b    #18,regc(regs)    ;Search for next file?
  1652.     bne.s    bdos17k        ;No.
  1653.     lea    srchnam,a0
  1654.     lea    renname,a1
  1655.     moveq    #10,d0
  1656. 1$    cmp.b    (a0)+,(a1)+    ;Search for the same name as last time?
  1657.     bne    results        ;No - exit with failed status.
  1658.     dbra    d0,1$
  1659.     tst.l    fibsize        ;Is the last file completely done?
  1660.     beq.s    bdos17k        ;Yes - try for another one.
  1661.     pea    0        ;Housekeeping for the stack
  1662.     bra.s    bdos17b        ;Create an entry for the next extent.
  1663. bdos17k    move.l    #null,d1
  1664.     move.l    #ACCESS_READ,d2
  1665.     sys    Lock        ;Get a file lock.
  1666.     tst.l    d0        ;Did we fail?
  1667.     beq    results     ;Yes - exit.
  1668.     move.l    d0,-(sp)    ;Save the lock.
  1669.     move.l    d0,d1        ;Put it here for Examine.
  1670.     move.l    #fib,d2
  1671.     lea    target,targbase
  1672.     move.w    newdmap,d0
  1673.     or.w    d0,acmap    ;Add drive to active drive map.
  1674.     cmpi.b    #18,regc(regs)    ;Search for next file?
  1675.     beq.s    bdos17n     ;Yes.
  1676.     sys    Examine     ;Set up to find the first file.
  1677.     tst.l    d0        ;Did we succeed?
  1678.     beq    bdos17x     ;No.
  1679. bdos17n move.l    (sp),d1
  1680.     move.l    #fib,d2
  1681.     sys    ExNext        ;Look for the next file.
  1682.     tst.l    d0        ;Did we succeed?
  1683.     beq    bdos17x     ;No.
  1684.     tst.l    fibtype     ;Is this a file entry?
  1685.     bpl    bdos17n     ;No - ignore subdirectory entries.
  1686.     clr.w    ext17        ;Clear extent number.
  1687.  
  1688. bdos17b    move.l    dmaaddr,a1    ;Build a fake FCB here.
  1689.     clr.b    (a1)+        ;Clear drive code.
  1690.     move.l    a1,-(sp)    ;The file name starts here.
  1691.     moveq    #10,d0
  1692. 1$    move.b    #' ',(a1)+    ;Clear file name and extension.
  1693.     dbra    d0,1$
  1694.     moveq    #19,d0
  1695. 2$    clr.b    (a1)+        ;Clear remainder of FCB to zeros.
  1696.     dbra    d0,2$
  1697.     lea    fibname,a0    ;A0 scans AmigaDOS file name.
  1698.     move.l    (sp)+,a1    ;A1 builds CP/M file name.
  1699. bdos17f tst.b    (a0)        ;End of file name?
  1700.     beq.s    2$        ;Yes.
  1701.     move.b    (a0)+,d0    ;Get the current character.
  1702.     cmpi.b    #'a',d0        ;Is it lower case?
  1703.     bcs.s    1$        ;No - leave it alone.
  1704.     cmpi.b    #'z'+1,d0
  1705.     bcc.s    1$
  1706.     subi.b    #'a'-'A',d0    ;Convert to upper case.
  1707. 1$    move.b    d0,(a1)+    ;Move the (possibly-converted) character.
  1708.     cmp.b    #'.',(a0)    ;Start of file name extension?
  1709.     bne.s    bdos17f     ;No.
  1710.     move.l    dmaaddr,d0
  1711.     add.w    #9,d0        ;Point to start of extension field.
  1712.     cmpa.l    d0,a1        ;Is file name too long?
  1713.     bhi    bdos17n     ;Yes - not a valid CP/M file name - ignore it.
  1714.     move.l    d0,a1
  1715.     addq.l    #1,a0        ;Skip over period.
  1716.     bra.s    bdos17f     ;Get the file name extension.
  1717. 2$    move.l    dmaaddr,d0
  1718.     add.w    #13,d0
  1719.     cmpa.l    d0,a1        ;Is the file name too long?
  1720.     bhi    bdos17n     ;Yes - ignore it.
  1721.     move.l    dmaaddr,a0
  1722.     addq.l    #1,a0
  1723.     lea    srchnam,a1
  1724.     moveq    #10,d0
  1725. 3$    cmpi.b    #'?',(a1)    ;Wild card character?
  1726.     bne.s    4$        ;No - compare it.
  1727.     addq.l    #1,a0        ;Skip over wild card character.
  1728.     addq.l    #1,a1
  1729.     dbra    d0,3$
  1730.     bra.s    bdos17w        ;We found a wild card match.
  1731. 4$    cmp.b    (a0)+,(a1)+    ;Does the file name match the search name?
  1732.     bne    bdos17n     ;No - try for another one.
  1733.     dbra    d0,3$        ;Check the next character.
  1734. bdos17w    lea    target,targbase
  1735.     moveq    #0,d1
  1736.     move.w    regd(regs),d1
  1737.     moveq    #0,d0
  1738.     move.b    12(targbase,d1.l),d0    ;Extent flag
  1739.     beq.s    bdos17h        ;Extent zero - take it.
  1740.     cmpi.b    #'?',d0        ;Search for all extents?
  1741.     beq.s    bdos17h        ;Yes - take this one.
  1742.     move.w    d0,ext17    ;Save extent number.
  1743.     moveq    #14,d1
  1744.     lsl.l    d1,d0        ;Multiply by 16384 to get byte displacement.
  1745.     sub.l    d0,fibsize    ;Beyond end of file?  (Adjust byte count!)
  1746.     bcs    bdos17n        ;Yes - forget this entry.
  1747.  
  1748. bdos17h    clr.b    newrega     ;Set success flag.
  1749.     move.l    dmaaddr,a0    ;The FCB is here.
  1750.     move.w    ext17,d0    ;Current extent number (counts up from zero)
  1751.     move.b    d0,12(a0)    ;Insert it into the FCB.
  1752.     andi.b    #$1F,12(a0)    ;Only the low-order 5 bits go here.
  1753.     lsr.l    #5,d0
  1754.     move.b    d0,14(a0)    ;High-order portion of extent number
  1755.     move.l    fibsize,d0    ;Number of bytes remaining
  1756.     move.b    #$80,15(a0)    ;Assume the current extent is full.
  1757.     cmpi.l    #16384,d0    ;Is it?
  1758.     bcc.s    1$        ;Yes.
  1759.     and.l    #$3FFF,d0    ;Number of bytes in the last extent
  1760.     add.w    #$7F,d0        ;(for rounding)
  1761.     lsr.l    #7,d0        ;Number of 128-byte records in extent
  1762.     move.b    d0,15(a0)    ;Store record count in FCB.
  1763. 1$    lea    target,targbase
  1764.     moveq    #0,d1
  1765.     move.w    regd(regs),d1
  1766.     cmpi.b    #'?',12(targbase,d1.l)    ;Search for all extents?
  1767.     bne.s    2$            ;No - we're done with this file.
  1768.     addq.w    #1,ext17    ;Bump extent counter.
  1769.     move.l    #16384,d0
  1770.     sub.l    d0,fibsize    ;Decrement remaining byte count
  1771.     bhi.s    bdos17x        ;There's more to do.
  1772. 2$    clr.l    fibsize        ;Set remaining count to zero.
  1773. bdos17x move.l    (sp)+,d1    ;Get the lock.
  1774.     beq    results        ;Ignore dummy entry for multi-extent file.
  1775.     sys    UnLock        ;Release the lock.
  1776.     bra    results
  1777.  
  1778. bdos19    add.l    targbase,d1    ;Delete file
  1779.     movea.l d1,a0        ;The FCB is here.
  1780.     bsr    mapdrv        ;Get drive map bit.
  1781.     and.w    romap,d1    ;Is this drive read-only?
  1782.     bne    roerr        ;Yes - abort the deletion.
  1783.     lea    opnname,a1    ;Build AmigaDOS file name here.
  1784.     move.l    a1,d1        ;We'll need it here.
  1785.     bsr    convfn        ;Make a file name.
  1786.     sys    DeleteFile    ;Delete the file.
  1787.     move.w    newdmap,d0
  1788.     or.w    d0,acmap    ;Add drive to active drive map.
  1789.     bra    results
  1790.  
  1791. bdos20    clr.b    newrega     ;Sequential read
  1792.     bsr    gethand
  1793.     tst.l    d1
  1794.     beq.s    1$
  1795.     move.l    dmaaddr,d2
  1796.     move.l    #128,d3
  1797.     sys    Read
  1798.     tst.l    d0        ;Were we successful?
  1799.     bgt    results     ;Yes.
  1800. 1$    move.b    #$1,newrega    ;Set end-of-file flag.
  1801.     bra    results
  1802.  
  1803. bdos21    clr.b    newrega     ;Sequential write
  1804.     bsr    gethand
  1805.     tst.l    d1
  1806.     beq.s    1$
  1807.     move.l    d1,-(sp)
  1808.     bsr    mapdrv        ;Get drive map bit.
  1809.     move.w    d1,d0
  1810.     move.l    (sp)+,d1
  1811.     and.w    romap,d0    ;Is this drive read-only?
  1812.     bne.s    roerr        ;Yes - error
  1813.     move.l    dmaaddr,d2
  1814.     move.l    #128,d3
  1815.     sys    Write
  1816.     tst.l    d0        ;Were we successful?
  1817.     bgt    results     ;Yes.
  1818. 1$    move.b    #$FF,newrega    ;Set failure flag.
  1819.     bra    results
  1820.  
  1821. bdos22    move.l    d1,-(sp)    ;Make new file
  1822.     bsr    gethand
  1823.     tst.l    d1        ;Is the file already open?
  1824.     beq.s    bdos22g        ;No - go ahead.
  1825.     clr.l    (a1)        ;Clear file handle table entry.
  1826.     sys    Close        ;Close the file.
  1827. bdos22g    move.l    (sp)+,d1
  1828.     add.l    #target,d1
  1829.     move.l    #MODE_NEWFILE,d2
  1830.     movea.l d1,a0        ;The FCB is here.
  1831.     bsr    mapdrv        ;Get the drive map bit.
  1832.     and.w    romap,d1    ;Is the drive read-only?
  1833.     beq    bdos15o     ;No - continue with BDOS 15 open routine
  1834. roerr    move.l    #1$,d1
  1835.     bsr    pstring     ;'BDOS Error on '
  1836.     bsr    ucase
  1837.     move.b    d0,d1
  1838.     add.b    #'A',d1
  1839.     bsr    pchar        ;Drive letter
  1840.     move.l    #2$,d1
  1841.     bsr    pstring     ;': R/O'
  1842.     bra    quitprg     ;Abort the program.
  1843.  
  1844. 1$    dc.b    'BDOS Error on $'
  1845. 2$    dc.b    ': R/O',cr,lf,'$'
  1846.  
  1847. bdos23    add.l    targbase,d1    ;Rename file
  1848.     movea.l d1,a0
  1849.     move.l    a0,-(sp)
  1850.     bsr    mapdrv        ;Get drive map bit.
  1851.     and.w    romap,d1    ;Is this drive read-only?
  1852.     bne    roerr        ;Yes - error
  1853.     lea    opnname,a1
  1854.     bsr    convfn        ;Convert old file name.
  1855.     move.l    (sp)+,a0
  1856.     lea    16(a0),a0
  1857.     lea    renname,a1
  1858.     bsr    convfn        ;Convert new file name.
  1859.     move.l    #opnname,d1
  1860.     move.l    #renname,d2
  1861.     sys    Rename        ;Rename the file.
  1862.     move.w    newdmap,d1
  1863.     or.w    d1,acmap    ;Add drive to active drive map.
  1864.     clr.b    newrega     ;Assume we succeeded.
  1865.     tst.l    d0        ;Did we fail?
  1866.     bne    results     ;No.
  1867.     move.b    #$FF,newrega
  1868.     bra    results
  1869.  
  1870. bdos24    move.w    acmap,regh(regs);Get active drive map
  1871.     bra    results
  1872.  
  1873. bdos25    move.b    4(targbase),newrega    ;Get default drive number
  1874.     andi.b    #$0F,newrega    ;Isolate drive bits.
  1875.     bra    results
  1876.  
  1877. bdos26    add.l    targbase,d1    ;Set file buffer address
  1878.     move.l    d1,dmaaddr
  1879.     bra    results
  1880.  
  1881. bdos27    move.w    #fakealv-fdos+$FF00,regh(regs)    ;Get allocation vector
  1882.     move.b    regl(regs),newrega    ;Make undocumented copy.
  1883.     move.b    regh(regs),regb(regs)
  1884.     move.l    #null,d1
  1885.     move.l    #ACCESS_READ,d2
  1886.     sys    Lock        ;Get a file lock.
  1887.     move.l    d0,d1        ;Did we fail?
  1888.     beq    results     ;Yes - exit.
  1889.     move.l    d0,-(sp)    ;Save the lock.
  1890.     move.l    #InfoData,d2
  1891.     sys    Info        ;Get disk information.
  1892.     tst.l    d0        ;Did we fail?
  1893.     beq    bdos27x        ;Yes - exit.
  1894.     lea    fakealv-fdos+$FF00,a0
  1895.     adda.l    targbase,a0    ;A0 loads allocation vector.
  1896.     move.b    #$F0,(a0)+    ;Initial allocation for directory
  1897.     clr.b    (a0)+
  1898.     move.l    a0,-(sp)
  1899.     move.l    id_NumBlocks,d1    ;Number of 512-byte blocks on disk
  1900.     addq.l    #3,d1
  1901.     lsr.l    #2,d1        ;Convert to 2048-byte blocks for CP/M.
  1902.     move.l    d1,d0
  1903.     subq.l    #1,d0
  1904.     move.b    d0,fakedpb+5    ;Insert high block number in DPB.
  1905.     lsr.l    #8,d0
  1906.     move.b    d0,fakedpb+6
  1907. 1$    clr.b    (a0)+        ;Clear remainder of allocation vector.
  1908.     dbra    d1,1$
  1909.     move.l    (sp)+,a0
  1910.     move.l    id_NumBlocksUsed,d0    ;Number of 512-byte blocks used
  1911.     moveq    #11,d1
  1912.     lsr.w    #2,d0        ;CP/M (2048-byte) blocks used
  1913.     beq.s    bdos27x        ;Nothing is allocated.
  1914.     move.w    d0,d1
  1915.     and.w    #7,d1        ;Number of bits to set in partial ALV byte
  1916.     beq.s    2$         ;No partial byte
  1917.     subq.w    #1,d1        ;Number of bits less one
  1918.     move.b    #$80,d2        ;Here's one bit.
  1919.     asr.b    d1,d2        ;Make some more.
  1920.     move.b    d2,(a0)+    ;Store partial allocation vector byte.
  1921. 2$    lsr.w    #3,d0        ;Number of ALV bytes to set all bits in
  1922.     beq    bdos27x        ;There are none - we're done.
  1923.     subq.w    #1,d0
  1924. 3$    move.b    #$FF,(a0)+    ;Set all bits in these ALV bytes.
  1925.     dbra    d0,3$
  1926. bdos27x    move.l    (sp)+,d1
  1927.     sys    UnLock        ;Release the file lock.
  1928.     bra    results
  1929.  
  1930. bdos28    move.b    4(targbase),d0    ;Protect drive
  1931.     andi.b    #$0F,d0     ;Current drive
  1932.     moveq    #1,d1
  1933.     lsl.w    d0,d1        ;Set up drive bit.
  1934.     or.w    d1,romap    ;Add it to read-only map.
  1935.     bra    results
  1936.  
  1937. bdos29    move.w    romap,regh(regs);Get read-only map
  1938.     bra    results
  1939.  
  1940. bdos30    equ    badbdos     ;Set file attributes
  1941.  
  1942. bdos31    move.w    #fakedpb-fdos+$FF00,regh(regs)    ;Get disk parameter block
  1943.     move.b    regl(regs),newrega    ;Make undocumented copy.
  1944.     move.b    regh(regs),regb(regs)
  1945.     bra    results
  1946.  
  1947. bdos32    cmp.b    #$FF,rege(regs) ;Get or set user code
  1948.     bne.s    1$        ;Set it.
  1949.     move.b    4(targbase),d0    ;Current drive and user code
  1950.     lsr.b    #4,d0        ;Set up user code.
  1951.     move.b    d0,newrega
  1952.     move.b    newrega,regl(regs)
  1953.     move.b    regh(regs),regb(regs)
  1954.     bra    results
  1955. 1$    andi.b    #$0F,4(targbase);Clear old user code.
  1956.     move.b    rege(regs),d0    ;Get new user code.
  1957.     lsl.b    #4,d0        ;Shift bits into position.
  1958.     or.b    d0,4(targbase)    ;Insert new user code.
  1959.     bra    results
  1960.  
  1961. bdos33    pea    _LVORead(a6)    ;Direct access read
  1962.     clr.b    newrega
  1963.     bsr    gethand
  1964.     bra.s    bdos34c     ;Use common read/write routine.
  1965.  
  1966. bdos34    pea    _LVOWrite(a6)    ;Direct access write
  1967.     clr.b    newrega
  1968.     bsr    gethand
  1969.     move.l    d1,-(sp)
  1970.     bsr    mapdrv        ;Get drive map bit.
  1971.     move.w    d1,d0
  1972.     move.l    (sp)+,d1
  1973.     and.w    romap,d0    ;Is this drive read-only?
  1974.     bne    roerr        ;Yes - error
  1975. bdos34c move.l    d1,-(sp)    ;Save file handle (common read/write routine)
  1976.     moveq    #0,d2
  1977.     move.b    35(a0),d2    ;Get seek address.
  1978.     rol.l    #8,d2
  1979.     move.b    34(a0),d2
  1980.     rol.l    #8,d2
  1981.     move.b    33(a0),d2
  1982.     rol.l    #7,d2        ;Convert record number to byte displacement.
  1983.     move.b    33(a0),32(a0)    ;Set up current record number in extent.
  1984.     andi.b    #$7F,32(a0)
  1985.     moveq    #14,d0
  1986.     ror.l    d0,d2
  1987.     move.b    d2,12(a0)    ;Current extent number
  1988.     rol.l    d0,d2
  1989.     moveq    #-1,d3
  1990.     sys    Seek        ;Seek to desired position.
  1991.     move.l    (sp)+,d1    ;Get the file handle again.
  1992.     move.l    (sp)+,a0    ;Address of read or write routine
  1993.     tst.l    d0        ;Were we successful?
  1994.     bmi    1$        ;No.
  1995.     move.l    dmaaddr,d2
  1996.     move.l    #128,d3
  1997.     jsr    (a0)        ;Read or write the desired record.
  1998.     tst.l    d0        ;Were we successful?
  1999.     bgt    results     ;Yes.
  2000. 1$    move.b    #6,newrega    ;Set failure (invalid address) flag.
  2001.     bra    results
  2002.  
  2003. bdos35    bsr    gethand     ;Get file end address
  2004.     move.l    a0,-(sp)    ;Pointer to FCB
  2005.     move.l    d1,-(sp)
  2006.     moveq    #0,d2
  2007.     moveq    #1,d3
  2008.     sys    Seek        ;Jump to end of file.
  2009.     move.l    (sp)+,d1
  2010.     move.l    d0,d2        ;Old position
  2011.     moveq    #-1,d3
  2012.     sys    Seek        ;Go back to the old position.
  2013.     move.l    (sp)+,a0    ;Restore FCB pointer.
  2014.     add.l    #$7F,d0        ;Adjust for partial final block, if any.
  2015.     lsr.l    #7,d0        ;File size in 128-byte records
  2016.     move.b    d0,33(a0)    ;Insert file size into FCB.
  2017.     lsr.l    #8,d0
  2018.     move.b    d0,34(a0)
  2019.     lsr.l    #8,d0
  2020.     move.b    d0,35(a0)
  2021.     bra    results
  2022.  
  2023. bdos36    bsr    gethand     ;Get direct address
  2024.     move.l    a0,-(sp)    ;Save pointer to FCB.
  2025.     moveq    #0,d2
  2026.     moveq    #0,d3
  2027.     sys    Seek        ;Seek to current position.
  2028.     move.l    (sp)+,a0    ;Restore FCB pointer.
  2029.     lsr.l    #7,d0        ;Convert to 128-byte record number.
  2030.     beq.s    bdos36m     ;Beginning of file
  2031.     subq.l    #1,d0        ;Back up to record just read.
  2032. bdos36m move.b    d0,33(a0)    ;Insert position into FCB.
  2033.     lsr.l    #8,d0
  2034.     move.b    d0,34(a0)
  2035.     lsr.l    #8,d0
  2036.     move.b    d0,35(a0)
  2037.     bra    results
  2038.  
  2039. *
  2040. * Individual BIOS service routines
  2041. *
  2042. bios01    bra    quitprg     ;Warm boot
  2043.  
  2044. bios02    equ    bdos11        ;Console status check
  2045.  
  2046. bios03    equ    bdos01        ;Console input byte
  2047.  
  2048. bios04    move.b    regc(regs),d1    ;Console output byte
  2049.     clr.b    testdol     ;Allow dollar signs
  2050.     bsr    pchar
  2051.     bra    results
  2052.  
  2053. bios05    pea    regc(regs)    ;List output byte
  2054.     bra    bdos05t
  2055.  
  2056. bios06    equ    badbios     ;Punch output byte
  2057.  
  2058. bios07    equ    badbios     ;Reader input byte
  2059.  
  2060. bios08    equ    badbios     ;Home disk
  2061.  
  2062. bios09    equ    badbios     ;Select disk
  2063.  
  2064. bios10    equ    badbios     ;Set track
  2065.  
  2066. bios11    equ    badbios     ;Set sector
  2067.  
  2068. bios12    equ    badbios     ;Set DMA address
  2069.  
  2070. bios13    equ    badbios     ;Read disk
  2071.  
  2072. bios14    equ    badbios     ;Write disk
  2073.  
  2074. bios15    move.b    #$FF,newrega    ;List status
  2075.     bra    results
  2076.  
  2077.  
  2078. *
  2079. * Set "newdmap" with a bit corresponding to the drive code in the
  2080. *  FCB pointed to by A0 (or the default drive if necessary).
  2081. *  The contents of "newdmap" will also be in the low-order word of D1.
  2082. *  Register D0 will be set to 0 for drive A:, 1 for drive B:, 2 for C:, etc.
  2083. *  The contents of register A0 will be preserved.
  2084. *
  2085. mapdrv    move.b    (a0),d0     ;Drive code
  2086.     bne.s    1$        ;The drive is specified.
  2087.     move.b    4(targbase),d0    ;Get the default drive.
  2088.     andi.b    #$0F,d0
  2089.     addq    #1,d0
  2090. 1$    subq.b    #1,d0        ;Adjust drive code so that 0 is A:, etc.
  2091.     moveq    #1,d1
  2092.     lsl.w    d0,d1        ;Set up drive map bit.
  2093.     move.w    d1,newdmap    ;Save it.
  2094.     rts
  2095.  
  2096.  
  2097. *
  2098. * Simulation of the Z-80 LD A,R instruction -
  2099. *  load a random 7-bit value into the accumulator.
  2100. *
  2101. movear    move.l    #dtstamp,d1
  2102.     movem.l a1/a6,-(sp)
  2103.     move.l    _DOSBase,a6
  2104.     sys    DateStamp
  2105.     movem.l (sp)+,a1/a6
  2106.     move.b    dtstamp+11,rega ;Low-order 7 bits of timer ticks
  2107.     andi.b    #$7F,rega
  2108.     jmp    (return)
  2109.  
  2110.  
  2111. *
  2112. * End of program, one way or another
  2113. *
  2114. quitprg move.l    savesp,sp    ;Restore stack pointer.
  2115.     bsr    dmpstr        ;Dump any outstanding console output.
  2116.     clr.w    romap        ;Clear the read-only map.
  2117.  
  2118. * Close the serial.device if it was used.
  2119.     tst.l    rpport
  2120.     beq.s    closlis     ;Nothing was opened.
  2121.     tst.l    wpport
  2122.     beq.s    q3        ;The output port wasn't opened.
  2123.  
  2124.     lea    writreq,a1
  2125.     move.l    _SysBase,a6
  2126.     sys    CloseDevice    ;Close the serial output device.
  2127.  
  2128.     move.l    wpport,-(sp)
  2129.     jsr    _DeletePort    ;Delete the serial output port.
  2130.     addq.l    #4,sp
  2131.     clr.l    wpport
  2132.  
  2133. q3    lea    readreq,a1
  2134.     move.l    _SysBase,a6
  2135.     sys    CloseDevice    ;Close the serial input device.
  2136.  
  2137.     move.l    rpport,-(sp)
  2138.     jsr    _DeletePort    ;Delete the serial input port.
  2139.     addq.l    #4,sp
  2140.     clr.l    rpport
  2141.  
  2142. * If the list device was used, close it.
  2143. closlis tst.b    listopn     ;Is the printer open?
  2144.     beq.s    closprt     ;No.
  2145.     move.l    prthand,d1
  2146.     sys    Close        ;Close the printer.
  2147. closprt clr.b    listopn     ;Reset the "printer-open" flag.
  2148.  
  2149. * If any files were left open by the last program, close them.
  2150.     lea    handles,a0
  2151.     moveq    #(handlen-handles)/16-1,d0
  2152. closall move.l    (a0),d1
  2153.     beq.s    closnxt     ;This file isn't open.
  2154.     movem.l a0/d0,-(sp)
  2155.     move.l    _DOSBase,a6
  2156.     sys    Close        ;Close this file.
  2157.     movem.l (sp)+,a0/d0
  2158.     clr.l    (a0)        ;Clear the file handle.
  2159. closnxt    lea    16(a0),a0
  2160.     dbra    d0,closall
  2161. * Check whether we should quit the simulation.
  2162.     tst.b    quitflg     ;Exit the simulator?
  2163.     bne.s    exitsim     ;Yes.
  2164.     tst.b    cmdflag     ;Was .COM file loaded from command line?
  2165.     beq    nextprg     ;No - re-display the command prompt.
  2166. * Terminate execution of the simulator.
  2167. exitsim move.l    rawhand,d1    ;Is RAW: open?
  2168.     beq.s    closlib     ;No.
  2169.     move.l    _DOSBase,a6
  2170.     sys    Close        ;Close RAW:
  2171. closlib move.l    _SysBase,a6
  2172.     move.l    _DOSBase,a1
  2173.     sys    CloseLibrary    ;Close dos.library.
  2174.     moveq    #0,d0        ;Return with no error.
  2175.     rts            ;All done
  2176.     page
  2177. *************************************************************************
  2178. *                                    *
  2179. *    AmigaDOS interface routines                    *
  2180. *                                    *
  2181. *************************************************************************
  2182.  
  2183. *
  2184. * Get a line from the console.    CP/M BDOS 10 conventions are used.
  2185. *  A0 is assumed to point to the start of the buffer.
  2186. *  If the first character encountered is a control-C, this routine
  2187. *  exits, leaving just the control-C in the buffer.
  2188. *
  2189. getline movem.l d2-d3/a0-a1/a6,-(sp)
  2190.     bsr    dmpstr        ;Flush the screen buffer first.
  2191.     move.l    _DOSBase,a6
  2192.     lea    2(a0),a1    ;The current character loads here.
  2193.     clr.b    1(a0)        ;Clear character count.
  2194. getlinl move.l    rawhand,d1    ;Read from RAW:
  2195.     move.l    a1,d2        ; into current position
  2196.     moveq    #1,d3        ;  for a length of one byte.
  2197.     movem.l d1-d3/a0-a1,-(sp)
  2198.     sys    Read        ;Get a character.
  2199.     movem.l (sp)+,d1-d3/a0-a1
  2200.     cmpi.b    #cr,(a1)    ;Did we get a carriage return?
  2201.     beq.s    getlinc     ;Yes - stop here.
  2202.     cmpi.b    #lf,(a1)    ;Stop on a line feed too.
  2203.     beq.s    getlinc
  2204.     cmpi.b    #bs,(a1)    ;Backspace?
  2205.     bne.s    getlinp     ;No.
  2206.     tst.b    1(a0)        ;Do we have anything yet?
  2207.     beq.s    getlinl     ;No - ignore the backspace.
  2208.     subq.l    #1,a1        ;Back over the previous character.
  2209.     subq.b    #1,1(a0)    ;Decrement character count.
  2210.     movem.l a0-a1,-(sp)
  2211.     move.l    #bsmsg,d1
  2212.     bsr    pstring     ;Erase the previous character on the screen.
  2213.     movem.l (sp)+,a0-a1
  2214.     bra.s    getlinl
  2215. bsmsg    dc.b    bs,' ',bs,'$'    ;Erases the previous character
  2216. getlinp movem.l a0-a1,-(sp)
  2217.     sys    Write        ;Echo the current character.
  2218.     movem.l (sp)+,a0-a1
  2219.     addq.b    #1,1(a0)    ;Bump character count.
  2220.     move.b    1(a0),d0    ;Number of bytes read so far.
  2221.     cmpi.b    #3,(a1)+    ;Did we get a control-C?
  2222.     bne.s    1$        ;No.
  2223.     cmpi.b    #1,d0        ;Is is the first character?
  2224.     beq.s    getlinx     ;Yes - exit now.
  2225. 1$    cmp.b    (a0),d0     ;Is the buffer full?
  2226.     bne.s    getlinl     ;No - try for another character.
  2227.     bra.s    getlinx
  2228. getlinc bsr    pcrlf        ;Carriage return or line feed
  2229. getlinx movem.l (sp)+,d2-d3/a0-a1/a6
  2230.     rts            ;Exit.
  2231.  
  2232. *
  2233. * Display the message pointed to by D1.
  2234. *  The message must be terminated by a dollar sign.
  2235. *
  2236. pstring movem.l d2-d3/a1-a2,-(sp)    ;Save work registers.
  2237.     move.l    d1,a0        ;A0 scans the message.
  2238.     bset    #0,testdol    ;Suppress $ test?
  2239.     beq.s    pstrs        ;Yes (used by BDOS/BIOS character output)
  2240.     cmpi.b    #'$',(a0)    ;Null string?
  2241.     beq    pstrx        ;Yes - do nothing.
  2242. pstrs    move.l    strptr,a1    ;A1 loads the output buffer.
  2243.     move.l    #strbufn,d3
  2244.     sub.l    a1,d3        ;Number of bytes left in buffer
  2245.     ifne    h19
  2246.     moveq    #0,d0
  2247.     move.w    esclen,d0    ;Is a partial escape sequence saved?
  2248.     beq.s    pstrl        ;No.
  2249.     lea    escbuf,a2
  2250.     adda.l    d0,a2        ;Continue loading it here.
  2251.     clr.w    esclen        ;Reset "saved length" counter.
  2252.     cmpi.w    #2,d0        ;Did we just save one byte?
  2253.     bcs.s    pstresc     ;Yes - get the remainder.
  2254.     bhi    pstreY2     ;Get the last cursor positioning byte.
  2255.     subq.l    #1,a2        ;Back over dummy byte.
  2256.     bra    pstreY1     ;Get both cursor positioning bytes.
  2257.     endc
  2258. pstrl    cmpi.b    #lf,(a0)    ;Line feed?
  2259.     bne.s    notlf        ;No.
  2260.     lea    escbuf,a2    ;Translate it to a cursor-down sequence.
  2261.     move.b    #$9B,(a2)+
  2262.     move.b    #'B',(a2)+
  2263.     addq.l    #1,a0
  2264.     bra    pstrsub
  2265. notlf:
  2266.     ifne    h19
  2267. * Optional H19 escape sequence translation
  2268.     cmpi.b    #esc,(a0)    ;Escape character?
  2269.     bne    pstrm        ;No - treat it normally.
  2270.     lea    escbuf,a2    ;Build translated escape sequence here.
  2271.     move.b    #$9B,(a2)+    ;Start with an AmigaDOS escape character.
  2272.     addq.l    #1,a0        ;Check the next character.
  2273.     cmpi.b    #'$',(a0)    ;End of string?
  2274.     bne.s    pstresc     ;No - analyze the sequence.
  2275.     move.w    #1,esclen    ;We've saved one byte for next time.
  2276.     bra    pstrw        ;Write everything up to the ESC character.
  2277. pstresc move.b    (a0)+,d0
  2278.     cmpi.b    #'[',d0     ;ANSI escape sequence?
  2279.     beq    pstrsub     ;Yes - pass the sequence with $9B header.
  2280.     cmpi.b    #'Y',d0
  2281.     beq.s    pstreY        ;Set cursor position.
  2282.     cmpi.b    #'@',d0
  2283.     beq.s    pstrein     ;Set insert mode.
  2284.     cmpi.b    #'A',d0
  2285.     bcs    pstreun     ;Unknown code - copy it as is.
  2286.     cmpi.b    #'O',d0
  2287.     beq.s    pstreO        ;Reset insert mode.
  2288.     bhi    pstreun     ;Unknown code
  2289.     move.l    a0,-(sp)
  2290.     lea    esctran(pc),a0    ;Translation table with offset
  2291.     move.b    -'A'(a0,d0.w),d2;Get the translated code.
  2292.     move.l    (sp)+,a0
  2293.     btst    #6,d2        ;Does the translated code stand alone?
  2294.     bne.s    1$        ;No.
  2295.     subq.l    #1,a2        ;Back over stored CSI character.
  2296. 1$    move.b    d2,(a2)+    ;Get the translated code.
  2297.     bra.s    pstrsub
  2298. esctran dc.b    'ABCD',ff,so,si,'H',$8D,'JKLMP' ;Escape sequence translation
  2299. pstrein move.b    #1,insflag    ;Set insert mode.
  2300.     bra.s    pstrsbx
  2301. pstreO    clr.b    insflag     ;Reset insert mode.
  2302.     bra.s    pstrsbx
  2303. pstreY    cmpi.b    #'Y',d0     ;Set cursor position
  2304.     bne.s    pstreun
  2305.     cmpi.b    #'$',(a0)    ;End of string?
  2306.     bne.s    pstreY1     ;No.
  2307.     move.w    #2,esclen    ;Indicate we need both position bytes.
  2308.     bra    pstrw        ;Finish the sequence next time.
  2309. pstreY1 moveq    #0,d0
  2310.     move.b    (a0)+,d0    ;Get the first position byte.
  2311.     bsr    pstrcvd     ;Convert to decimal in save area.
  2312.     move.b    #';',(a2)+    ;Add the separator character.
  2313.     cmpi.b    #'$',(a0)    ;End of string?
  2314.     bne.s    pstreY2     ;No.
  2315.     sub.l    #escbuf,a2    ;Number of bytes saved
  2316.     move.w    a2,esclen
  2317.     bra    pstrw        ;Get the last byte next time.
  2318. pstreY2 moveq    #0,d0
  2319.     move.b    (a0)+,d0    ;Get the last position byte.
  2320.     bsr    pstrcvd     ;Convert to decimal in save area.
  2321.     move.b    #'H',(a2)+    ;Terminate the sequence.
  2322.     bra.s    pstrsub
  2323. pstreun move.b    #esc,escbuf    ;Unidentified escape sequence -
  2324.     move.b    d0,(a2)+    ; pass it through as is.
  2325.     endc
  2326. * The translated escape sequence is now in "escbuf" -
  2327. *  copy it to the output buffer.
  2328. pstrsub move.l    a2,d0
  2329.     lea    escbuf,a2    ;A2 scans translated escape sequence.
  2330.     sub.l    a2,d0        ;Length of translated escape sequence
  2331.     subq.l    #1,d0
  2332. 1$    move.b    (a2)+,(a1)+    ;Copy substitution to output string.
  2333.     subq.w    #1,d3        ;Count down remaining length.
  2334.     dbra    d0,1$
  2335. pstrsbx cmpi.b    #'$',(a0)    ;End of string?
  2336.     beq    pstrw        ;Yes - write it out.
  2337.     tst.w    d3        ;Is the buffer full?
  2338.     bmi    pstrw        ;Yes - write out what we have.
  2339.     cmpi.b    #lf,-1(a0)    ;Line feed?
  2340.     bne    pstrl        ;No.
  2341.     tst.b    bufflag     ;Is console buffering in effect?
  2342.     beq    pstrl        ;No.
  2343.     move.l    a1,strptr
  2344.     bsr    dmpstr        ;Dump the buffer.
  2345.     move.l    strptr,a1
  2346.     bra    pstrl        ;Check for another escape sequence.
  2347. * Subroutine to convert the byte in D0 to a character string at (A2)+
  2348. pstrcvd subi.b    #' '-1,d0    ;Convert to binary row or column number.
  2349.     divu    #10,d0        ;Convert to tens and units.
  2350.     tst.w    d0        ;Is the number 10 or greater?
  2351.     beq.s    1$        ;No - just create a one-digit number.
  2352.     addi.b    #'0',d0     ;Convert the tens digit to ASCII.
  2353.     move.b    d0,(a2)+    ;Move it to the result field.
  2354. 1$    swap    d0        ;Get the units digit.
  2355.     addi.b    #'0',d0     ;Convert it to ASCII.
  2356.     move.b    d0,(a2)+
  2357.     rts
  2358. * Normal character processing
  2359. pstrm    tst.b    insflag     ;Are we in insert mode?
  2360.     beq.s    pstrmv        ;No.
  2361.     lea    escbuf,a2
  2362.     move.b    #$9B,(a2)+    ;Build an insert-character sequence.
  2363.     move.b    #'@',(a2)+
  2364.     move.b    (a0)+,(a2)+    ;Here's the character to insert.
  2365.     bra.s    pstrsub     ;Use the substitution routine.
  2366. pstrmv    move.b    (a0)+,(a1)+    ;Move one character.
  2367.     tst.b    bufflag     ;Is console buffering in effect?
  2368.     beq.s    2$        ;No.
  2369.     cmpi.b    #cr,-1(a0)    ;Carriage return?
  2370.     beq.s    1$        ;Yes - dump the current segment.
  2371.     cmpi.b    #bel,-1(a0)    ;Bell?
  2372.     bne.s    2$        ;No - continue buffering.
  2373. 1$    move.l    a1,strptr
  2374.     bsr    dmpstr        ;Dump the buffer.
  2375.     move.l    strptr,a1
  2376. 2$    cmpi.b    #'$',(a0)    ;Test for end of string.
  2377.     dbeq    d3,pstrl    ;Loop until we get there or buffer is full.
  2378. pstrw    move.l    a1,strptr
  2379.     tst    d3        ;Is the buffer full?
  2380.     bmi.s    1$        ;Yes - dump it regardless.
  2381.     tst.b    bufflag     ;Is console buffering in effect?
  2382.     bne.s    2$        ;Yes - don't write anything yet.
  2383. 1$    bsr    dmpstr        ;Dump the buffer.
  2384.     move.l    strptr,a1
  2385. 2$    tst    d3        ;Did the output buffer overflow?
  2386.     bmi    pstrs        ;Yes - get another section of the message.
  2387. pstrx    movem.l (sp)+,d2-d3/a1-a2    ;Restore registers
  2388.     rts
  2389. *
  2390. * Write the contents of "strbuf" to RAW: if possible, or stdout if not.
  2391. *  The number of bytes to be written is calculated from "strptr".
  2392. *
  2393. dmpstr    movem.l d2-d3/a0-a1/a6,-(sp)
  2394.     move.l    strptr,d3
  2395.     move.l    #strbuf,d2    ;Address of buffer
  2396.     move.l    d2,strptr    ;Reset the buffer pointer.
  2397.     sub.l    d2,d3        ;Length of output string
  2398.     beq.s    2$        ;Zero - don't write anything.
  2399.     move.l    rawhand,d1    ;Assume we're writing to RAW:
  2400.     bne.s    1$
  2401.     move.l    stdout,d1    ;We don't have RAW: - use stdout.
  2402. 1$    move.l    _DOSBase,a6
  2403.     sys    Write        ;Display the line.
  2404. 2$    movem.l (sp)+,d2-d3/a0-a1/a6
  2405.     rts
  2406.  
  2407. *
  2408. * Convert the file name in the FCB pointed to by A0
  2409. *  to an AmigaDOS-format file name in the field pointed to by A1.
  2410. *  D0 is the only other register used by this routine.
  2411. *
  2412. convfn    move.l    a1,-(sp)
  2413.     move.l    a0,-(sp)    ;Save start address of FCB.
  2414.     move.b    (a0)+,d0    ;Get the drive code.
  2415.     bne.s    1$        ;We have a drive code.
  2416.     move.b    target+4,d0    ;Use the default drive code.
  2417.     andi.b    #$0F,d0
  2418.     addq.b    #1,d0        ;Start at 1 for drive A:.
  2419. 1$    cmpi.b    #1,d0        ;Is it drive A:?
  2420.     beq.s    4$        ;Yes - don't add anything special.
  2421.     move.b    #'C',(a1)+
  2422.     move.b    #'P',(a1)+    ;Set up the prefix CPMx:
  2423.     move.b    #'M',(a1)+    ; where x is the drive letter.
  2424.     add.b    #'A'-1,d0
  2425.     move.b    d0,(a1)+
  2426.     move.b    target+4,d0    ;Get user number.
  2427.     lsr.b    #4,d0        ;Move it to low-order 4 bits.
  2428.     beq.s    3$        ;Don't insert user number if it's zero.
  2429.     move.b    #'0',(a1)+    ;Assume user number is less than 10.
  2430.     cmpi.b    #10,d0        ;Is user number 10 or greater?
  2431.     bcs.s    2$        ;No.
  2432.     move.b    #'1',-1(a1)    ;Change the first digit to 1.
  2433.     subi.b    #10,d0
  2434. 2$    addi.b    #'0',d0     ;Convert user number to ASCII.
  2435.     move.b    d0,(a1)+    ;Insert user number into file spec.
  2436. 3$    move.b    #':',(a1)+
  2437. 4$    moveq    #7,d0        ;Maximum of 8 characters for file name
  2438. convfn1 cmpi.b    #' ',(a0)    ;End of file name?
  2439.     beq.s    3$        ;Yes
  2440.     cmpi.b    #'*',(a0)    ;Wild card?
  2441.     bne.s    1$        ;No.
  2442.     move.b    #'#',(a1)+    ;Convert to AmigaDOS format.
  2443.     move.b    #'?',(a1)+
  2444.     addq.l    #1,a0        ;Skip over the asterisk.
  2445.     bra.s    2$
  2446. 1$    move.b    (a0)+,(a1)+    ;Move one character of file name.
  2447. 2$    dbra    d0,convfn1    ;Try for more.
  2448. 3$    movea.l (sp)+,a0    ;Back to start of FCB.
  2449.     lea    9(a0),a0    ;Go to start of file name extension.
  2450.     cmpi.b    #' ',(a0)    ;Do we have an extension?
  2451.     beq.s    convfnx     ;No.
  2452.     move.b    #'.',(a1)+    ;Insert extension separator.
  2453.     moveq    #2,d0        ;Maximum of 3 characters for extension.
  2454. convfn2 cmpi.b    #' ',(a0)    ;End of extension?
  2455.     beq.s    convfnx     ;Yes.
  2456.     cmpi.b    #'*',(a0)    ;Wild card?
  2457.     bne.s    1$        ;No.
  2458.     move.b    #'#',(a1)+    ;Convert to AmigaDOS format.
  2459.     move.b    #'?',(a1)+
  2460.     addq.l    #1,a0        ;Skip over the asterisk.
  2461.     bra.s    2$
  2462. 1$    move.b    (a0)+,(a1)+    ;Move one character of extension.
  2463. 2$    dbra    d0,convfn2    ;Try for more.
  2464. convfnx clr.b    (a1)        ;Terminate file name string.
  2465.     move.l    (sp)+,a1
  2466.     rts
  2467.  
  2468. *
  2469. * Get the file handle indicated by the first 12 bytes of the CP/M FCB
  2470. *  whose CP/M address is in D1.  The file handle (if found) is copied
  2471. *  to D1 from the file handle table entry (which is pointed to by A1).
  2472. *  If the file handle cannot be found, D1 will be set to zero.
  2473. *  In any event, A0 will be set to point to the FCB.
  2474. *
  2475. gethand    lea    0(targbase,d1.l),a0    ;The FCB is here.
  2476.     lea    handles,a1    ;A1 scans the file handle table.
  2477.     moveq    #(handlen-handles)/16-1,d0
  2478. 1$    movem.l    d0/a0-a1,-(sp)
  2479.     tst.l    (a1)        ;Is this entry empty?
  2480.     beq.s    3$        ;Yes - ignore it.
  2481.     addq.l    #4,a1        ;Skip over to file name in table.
  2482.     moveq    #11,d1
  2483. 2$    cmp.b    (a0)+,(a1)+    ;Compare first 12 bytes of FCB with table.
  2484.     bne.s    3$        ;No match.
  2485.     dbra    d1,2$
  2486.     movem.l    (sp)+,d0/a0-a1
  2487.     move.l    (a1),d1        ;Here's the file handle.
  2488.     rts
  2489. 3$    movem.l    (sp)+,d0/a0-a1
  2490.     lea    16(a1),a1    ;Try the next table entry.
  2491.     dbra    d0,1$
  2492.     moveq    #0,d1        ;Couldn't find the handle!
  2493.     rts
  2494.     page
  2495. *************************************************************************
  2496. *                                    *
  2497. *    Serial port routines                        *
  2498. *                                    *
  2499. *************************************************************************
  2500.  
  2501. *
  2502. * Read a byte from the port whose number is in D0.
  2503. *  A0 points to where to put it.
  2504. *
  2505. inp    movem.l a1/a6/d2-d3,-(sp)
  2506.     cmp.b    #$14,d0     ;Port 14?
  2507.     bne.s    inp15        ;No.
  2508.     move.l    a0,-(sp)
  2509.     tst.l    rpport        ;Is serial.device open?
  2510.     bne.s    1$        ;Yes.
  2511.     bsr    initser     ;Set up serial.device.
  2512. 1$    bsr    checkio
  2513.     tst.l    d0        ;Is a character ready?
  2514.     beq.s    2$        ;No - give the previous one again.
  2515.     bsr    serread     ;Read the new character.
  2516. 2$    move.l    (sp)+,a0
  2517.     move.b    charin,(a0)    ;Move it to user's area.
  2518.     bra.s    inpx
  2519. inp15    cmp.b    #$15,d0     ;Port 15?
  2520.     bne.s    inpx        ;No - ignore it.
  2521.     move.b    #7,(a0)     ;Assume a character is ready.
  2522.     move.l    a0,-(sp)
  2523.     bsr    checkio     ;Check whether a character is ready.
  2524.     move.l    (sp)+,a0
  2525.     tst.l    d0        ;Is a character ready?
  2526.     bne.s    inpx        ;Yes.
  2527.     move.b    #5,(a0)     ;Don't set "receiver ready" bit.
  2528. inpx    movem.l (sp)+,a1/a6/d2-d3
  2529.     rts
  2530.  
  2531. *
  2532. * Write the byte pointed to by A0 to the port whose number is in D0.
  2533. *
  2534. outp    movem.l a1/a6/d2-d3,-(sp)
  2535.     cmp.l    #$14,d0     ;Port 14?
  2536.     bne.s    outpx        ;No - ignore it.
  2537.     move.b    (a0),charout    ;Character to write
  2538.     tst.l    rpport        ;Is serial.device open?
  2539.     bne.s    1$        ;Yes.
  2540.     bsr    initser     ;Set up serial.device.
  2541. 1$    bsr    serwrit     ;Write the character.
  2542. outpx    movem.l (sp)+,a1/a6/d2-d3
  2543.     rts
  2544.  
  2545. *
  2546. * Initialize the serial port.
  2547. *
  2548. initser:
  2549.  
  2550. * Open a reply port for the serial input device.
  2551.     lea    readreq,a0
  2552.     move.w    #rsize-1,d0
  2553. 1$    clr.b    (a0)+        ;Clear the I/O request block.
  2554.     dbra    d0,1$
  2555.     clr.l    -(sp)
  2556.     move.l    #2$,-(sp)
  2557.     jsr    _CreatePort    ;rpport = CreatePort ("Read_RS", NULL);
  2558.     addq.l    #8,sp
  2559.     move.l    d0,rpport
  2560.     move.l    d0,r_ReplyPort
  2561.     bne.s    openin
  2562.     move.l    #3$,d1
  2563.     bsr    pstring
  2564.     bra    quitprg
  2565. 2$    dc.b    'Read_RS',0
  2566. 3$    dc.b    'Can''t create input port for serial.device!',cr,lf,'$'
  2567.  
  2568. * Open the serial input device.
  2569. openin    move.w    #rsize,r_MLength
  2570.     move.b    #SERFLAGS,r_SerFlags
  2571.     move.l    #CTLCHAR,r_CtlChar
  2572.     lea    1$,a0
  2573.     moveq    #0,d0
  2574.     lea    readreq,a1
  2575.     moveq    #0,d1
  2576.     move.l    _SysBase,a6
  2577.     sys    OpenDevice
  2578.     tst.l    d0        ;Were we successful?
  2579.     beq.s    setin        ;Yes.
  2580.     move.l    #2$,d1
  2581.     bsr    pstring
  2582.     bra    quitprg
  2583. 1$    dc.b    'serial.device',0
  2584. 2$    dc.b    'Can''t open serial.device!',cr,lf,'$'
  2585.  
  2586. setin    move.l    baud,r_Baud
  2587.     move.b    bits,r_ReadLen    ;Number of bits per character
  2588.     move.b    bits,r_WriteLen
  2589.     move.w    #SDCMD_SETPARAMS,r_Command
  2590.     lea    readreq,a1
  2591.     move.l    _SysBase,a6
  2592.     sys    DoIO        ;Set new input port parameters.
  2593.  
  2594. * Set up the serial output port.
  2595.     lea    readreq,a0
  2596.     lea    writreq,a1
  2597.     move.w    #wsize-1,d0
  2598. copw    move.b    (a0)+,(a1)+    ;Clone the read request block.
  2599.     dbra    d0,copw
  2600.     clr.l    -(sp)
  2601.     move.l    #1$,-(sp)
  2602.     jsr    _CreatePort    ;wpport = CreatePort ("Write_RS", NULL);
  2603.     addq.l    #8,sp
  2604.     move.l    d0,wpport
  2605.     move.l    d0,w_ReplyPort
  2606.     bne.s    startup
  2607.     move.l    #2$,d1
  2608.     bsr    pstring
  2609.     bra    quitprg
  2610. 1$    dc.b    'Write_RS',0
  2611. 2$    dc.b    'Can''t create output port for serial.device!',cr,lf,'$'
  2612.  
  2613. startup bsr    setbaud     ;Set parameters and start reading.
  2614.     rts
  2615.  
  2616. *
  2617. * Return TRUE (D0 <> 0) if the serial port has a character.
  2618. *
  2619. checkio lea    readreq,a1
  2620.     move.l    _SysBase,a6
  2621.     sys    CheckIO
  2622.     rts
  2623.  
  2624. *
  2625. * Set the serial port's baud rate, number of data bits, etc.
  2626. *
  2627. setbaud tas    frstset     ;Is this the first call?
  2628.     beq.s    1$        ;Yes - input port is set up.
  2629.     lea    readreq,a1
  2630.     move.l    _SysBase,a6
  2631.     sys    AbortIO     ;Abort the outstanding read.
  2632.     move.l    baud,r_Baud    ;Baud rate
  2633.     move.b    bits,r_ReadLen    ;Number of bits per character
  2634.     move.b    bits,r_WriteLen
  2635.     move.w    #SDCMD_SETPARAMS,r_Command
  2636.     lea    readreq,a1
  2637.     move.l    _SysBase,a6
  2638.     sys    DoIO        ;Set new input port parameters.
  2639. 1$    move.w    #CMD_READ,r_Command
  2640.     move.l    #1,r_Length
  2641.     move.l    #charinb,r_Data
  2642.     lea    readreq,a1
  2643.     move.l    _SysBase,a6
  2644.     sys    SendIO        ;Start reading again.
  2645. * Now set up the output port - this one is more straightforward.
  2646.     move.l    baud,w_Baud
  2647.     move.b    bits,w_ReadLen
  2648.     move.b    bits,w_WriteLen
  2649.     move.w    #SDCMD_SETPARAMS,w_Command
  2650.     lea    writreq,a1
  2651.     move.l    _SysBase,a6
  2652.     sys    DoIO
  2653.     rts
  2654.  
  2655. *
  2656. * Write the byte in "charout" to the serial port.
  2657. *
  2658. serwrit move.w    #CMD_WRITE,w_Command
  2659.     move.l    #1,w_Length
  2660.     move.l    #charout,w_Data
  2661.     lea    writreq,a1
  2662.     move.l    _SysBase,a6
  2663.     sys    DoIO
  2664.     rts
  2665.  
  2666. *
  2667. * Read a byte from the serial port into "charin".
  2668. *  If a byte isn't ready, this routine will wait until one is.
  2669. *
  2670. serread lea    readreq,a1
  2671.     move.l    _SysBase,a6
  2672.     sys    WaitIO        ;Wait until a character is ready.
  2673.     move.b    charinb,charin    ;Get the character from the buffer.
  2674.     move.w    #CMD_READ,r_Command
  2675.     move.l    #1,r_Length
  2676.     move.l    #charinb,r_Data
  2677.     lea    readreq,a1
  2678.     move.l    _SysBase,a6
  2679.     sys    SendIO        ;Get ready for the next character.
  2680.     rts
  2681.     page
  2682. *************************************************************************
  2683. *                                    *
  2684. *    Miscellaneous service routines                    *
  2685. *    (Inelegant, but rarely used so they stand as is.)        *
  2686. *                                    *
  2687. *************************************************************************
  2688.  
  2689. *
  2690. * Display the contents of D1 in hex.
  2691. *
  2692. pbyte    move.l    #$20018,d0    ;2 nybbles, 24-bit shift first
  2693.     bra.s    phex
  2694. pword    move.l    #$40010,d0    ;4 nybbles, 16-bit shift first
  2695.     bra.s    phex
  2696. paddr    move.l    #$60008,d0    ;6 nybbles, 8-bit shift first
  2697.     bra.s    phex
  2698. plong    move.l    #$80000,d0    ;8 nybbles, no shift first
  2699. phex    lea    workbuf,a0
  2700.     move.l    a0,-(sp)
  2701.     bsr    pdigits
  2702.     move.b    #'$',(a0)+
  2703.     move.l    (sp)+,d1
  2704.     bsr    pstring
  2705.     rts
  2706. *
  2707. * Convert the contents of D1 to hex at (A0).
  2708. *  On exit, A0 points to the next available byte.
  2709. *
  2710. ubyte    move.l    #$20018,d0    ;2 nybbles, 24-bit shift first
  2711.     bra.s    pdigits
  2712. uword    move.l    #$40010,d0    ;4 nybbles, 16-bit shift first
  2713.     bra.s    pdigits
  2714. uaddr    move.l    #$60008,d0    ;6 nybbles, 8-bit shift first
  2715.     bra.s    pdigits
  2716. ulong    move.l    #$80000,d0    ;8 nybbles, no shift first
  2717. pdigits rol.l    d0,d1        ;Do shift.
  2718.     bra.s    3$
  2719. 1$    swap    d0        ;Save nybble count.
  2720.     rol.l    #4,d1        ;Print variable in d1.
  2721.     move.l    d1,-(sp)
  2722.     and    #$F,d1        ;Isolate the current nybble.
  2723.     cmp    #$A,d1
  2724.     bcs.s    2$
  2725.     add.b    #'A'-'9'-1,d1    ;Adjust for digits A through F.
  2726. 2$    add.b    #'0',d1     ;Convert to ASCII.
  2727.     move.b    d1,(a0)+    ;Add to the result string.
  2728.     move.l    (sp)+,d1
  2729. 3$    swap    d0        ;Get nybble count.
  2730.     dbra    d0,1$
  2731.     rts
  2732.  
  2733. pchar    move.b    d1,workbuf    ;Print the character in D1.
  2734.     move.b    #'$',workbuf+1
  2735.     move.l    #workbuf,d1
  2736.     bsr    pstring
  2737.     rts
  2738.  
  2739. pspace    move.l    #1$,d1        ;Print a space.
  2740.     bsr    pstring
  2741.     rts
  2742. 1$    dc.b    ' $'
  2743.  
  2744. pcrlf    move.l    #1$,d1        ;Print a carriage return and line feed.
  2745.     bsr    pstring
  2746.     rts
  2747. 1$    dc.b    cr,lf,'$'
  2748.  
  2749. *
  2750. * Convert the hex string pointed to by A0 to long in d1.
  2751. *  Stops on the first invalid hex digit, which is returned in d0.
  2752. *  A0 is left pointing to this first invalid digit.
  2753. *  d2 = 1 if any valid digits were found, 0 otherwise.
  2754. *
  2755. atol    moveq    #0,d1
  2756.     moveq    #0,d2
  2757. 1$    move.b    (a0)+,d0    ;Get the current byte.
  2758.     cmpi.b    #$60,d0
  2759.     bcs.s    2$
  2760.     andi.b    #$5F,d0     ;Mask to upper case.
  2761. 2$    cmpi.b    #'0',d0     ;Check range (0..9,A..F).
  2762.     bcs.s    atolend
  2763.     cmpi.b    #'F',d0
  2764.     bhi.s    atolend
  2765.     cmpi.b    #'9',d0
  2766.     bls.s    3$
  2767.     cmpi.b    #'A',d0
  2768.     bcs.s    atolend
  2769. 3$    moveq    #1,d2        ;Valid characters entered, set flag.
  2770.     sub.b    #'0',d0     ;Convert to binary
  2771.     cmpi.b    #$9,d0        ;Digit in range 0..9?
  2772.     bls.s    4$        ;Yes - conversion is complete
  2773.     sub.b    #'A'-'9'-1,d0    ;Adjust digits A..F.
  2774. 4$    ext    d0        ;Convert to long.
  2775.     ext.l    d0
  2776.     asl.l    #4,d1        ;Tack it onto d1.
  2777.     add.l    d0,d1
  2778.     bra.s    1$        ;Try for another digit.
  2779. atolend subq.l    #1,a0        ;Back onto the first invalid digit.
  2780.     rts
  2781.     page
  2782. *************************************************************************
  2783. *                                    *
  2784. *    Instruction mnemonic table (used for tracing)            *
  2785. *                                    *
  2786. *************************************************************************
  2787.  
  2788.     data    data
  2789.  
  2790. * This table contains the mnemonic strings for the 8080/Z-80 opcodes.
  2791. *
  2792. * "q" denotes a register number in bits 3 through 5 of the opcode.
  2793. *    Values are interpreted as follows:
  2794. *        Normal 8080    Normal Z-80    DD prefix    FD prefix
  2795. *    000        B        B        B        B
  2796. *    001        C        C        C        C
  2797. *    010        D        D        D        D
  2798. *    011        E        E        E        E
  2799. *    100        H        H        XH        YH
  2800. *    101        L        L        XL        YL
  2801. *    110        M         (HL)        (IX+n)        (IY+n)
  2802. *    111        A        A        A        A
  2803. *
  2804. * "r" denotes a register number in bits 0 through 2 of the opcode.
  2805. *    Values are interpreted the same as for "q" above.
  2806. *
  2807. * "p" denotes a 2-bit register pair number in bits 4 and 5 of the opcode.
  2808. *    Values are interpreted as follows:
  2809. *        8080    Z-80
  2810. *    00    B    BC
  2811. *    01    D    DE
  2812. *    10    H    HL    (no DD or FD prefix)
  2813. *    10    IX    IX    (with DD prefix)
  2814. *    10    IX    IX    (with FD prefix)
  2815. *    11    SP    SP    (if opcode is below F0)
  2816. *    11    PSW    AF    (if opcode is F0 or greater)
  2817. *
  2818. * "h" is replaced by IX or IY if the opcode prefix is DD or FD respectively.
  2819. *  If the instruction is not prefixed, "h" is replaced by HL.
  2820. *
  2821. * "n" denotes an 8-bit number following the opcode.
  2822. *
  2823. * "a" denotes a 16-bit address following the opcode.
  2824.  
  2825. * Mnemonics for 8080 opcodes 00 through 3F
  2826. mnop008:
  2827.     dc.b    'NOP$        LXI  p,a$   STAX p$     INX  p$     ' ;00-03
  2828.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   RLC$        ' ;04-07
  2829.     dc.b    'EXAF$       DAD  p$     LDAX p$     DCX  p$     ' ;08-0B
  2830.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   RRC$        ' ;0C-0F
  2831.     dc.b    'DJNZ n$     LXI  p,a$   STAX p$     INX  p$     ' ;10-13
  2832.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   RAL$        ' ;14-17
  2833.     dc.b    'JR   n$     DAD  p$     LDAX p$     DCX  p$     ' ;18-1B
  2834.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   RAR$        ' ;1C-1F
  2835.     dc.b    'JRNZ n$     LXI  p,a$   ShD a$      INX  p$     ' ;20-23
  2836.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   DAA$        ' ;24-27
  2837.     dc.b    'JRZ  n$     DAD  p$     LhD a$      DCX  p$     ' ;28-2B
  2838.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   CMA$        ' ;2C-2F
  2839.     dc.b    'JRNC n$     LXI  p,a$   STA  a$     INX  p$     ' ;30-33
  2840.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   STC$        ' ;34-37
  2841.     dc.b    'JRC  n$     DAD  p$     LDA  a$     DCX  p$     ' ;38-3B
  2842.     dc.b    'INR  q$     DCR  q$     MVI  q,n$   CMC$        ' ;3C-3F
  2843.  
  2844. * Mnemonics for Z-80 opcodes 00 through 3F
  2845. mnop00z:
  2846.     dc.b    'NOP$        LD   p,a$   LD   (p),A$ INC  p$     ' ;00-03
  2847.     dc.b    'INC  q$     DEC  q$     LD   q,n$   RLCA$       ' ;04-07
  2848.     dc.b    'EX   AF,AF$ ADD  HL,p$  LD   A,(p)$ DEC  p$     ' ;08-0B
  2849.     dc.b    'INC  q$     DEC  q$     LD   q,n$   RRCA$       ' ;0C-0F
  2850.     dc.b    'DJNZ n$     LD   p,a$   LD   (p),A$ INC  p$     ' ;10-13
  2851.     dc.b    'INC  q$     DEC  q$     LD   q,n$   RLA$        ' ;14-17
  2852.     dc.b    'JR   n$     ADD  HL,p$  LD   A,(p)$ DEC  p$     ' ;18-1B
  2853.     dc.b    'INC  q$     DEC  q$     LD   q,n$   RRA$        ' ;1C-1F
  2854.     dc.b    'JR   NZ,n$  LD   p,a$   LD   (a),HL$INC  p$     ' ;20-23
  2855.     dc.b    'INC  q$     DEC  q$     LD   q,n$   DAA$        ' ;24-27
  2856.     dc.b    'JR   Z,n$   ADD  HL,p$  LD   HL,(a)$DEC  p$     ' ;28-2B
  2857.     dc.b    'INC  q$     DEC  q$     LD   q,n$   CPL$        ' ;2C-2F
  2858.     dc.b    'JR   NC,n$  LD   p,a$   LD   (a),A$ INC  p$     ' ;30-33
  2859.     dc.b    'INC  q$     DEC  q$     LD   q,n$   SCF$        ' ;34-37
  2860.     dc.b    'JR   C,n$   ADD  HL,p$  LD   A,(a)$ DEC  p$     ' ;38-3B
  2861.     dc.b    'INC  q$     DEC  q$     LD   q,n$   CCF$        ' ;3C-3F
  2862.  
  2863. * Mnemonics for opcodes 40 through 7f are easy - 76 is HLT
  2864. *  (HALT for Z-80), and all others are MOV (LD for Z-80).
  2865. mnop408 dc.b    'MOV  q,r$'
  2866. mnop40z dc.b    'LD   q,r$'
  2867. mnop768 dc.b    'HLT$'
  2868. mnop76z dc.b    'HALT$'
  2869.  
  2870. * Mnemonics for 8080 opcodes 80 through BF
  2871. mnop808:
  2872.     dc.b    'ADD  r$  ADC  r$  SUB  r$  SBB  r$  '    ;80-9F
  2873.     dc.b    'ANA  r$  XRA  r$  ORA  r$  CMP  r$  '    ;A0-BF
  2874.  
  2875. * Mnemonics for Z-80 opcodes 80 through BF
  2876. mnop80z:
  2877.     dc.b    'ADD  A,r$ADC  A,r$SUB  r$  SBC  A,r$'    ;80-9F
  2878.     dc.b    'AND  r$  XOR  r$  OR   r$  CP   r$  '    ;A0-BF
  2879.  
  2880. * Mnemonics for 8080 opcodes C0 through FF
  2881. *  These are interpreted by the same routine as for opcodes 00 through 3F.
  2882. mnopC08:
  2883.     dc.b    'RNZ$        POP  p$     JNZ  a$     JMP  a$     ' ;C0-C3
  2884.     dc.b    'CNZ  a$     PUSH p$     ADI  n$     RST  0$     ' ;C4-C7
  2885.     dc.b    'RZ$         RET$        JZ   a$     ILLEGAL$    ' ;C8-CB
  2886.     dc.b    'CZ   a$     CALL a$     ACI  n$     RST  1$     ' ;CC-CF
  2887.     dc.b    'RNC$        POP  p$     JNC  a$     OUT  n$     ' ;D0-D3
  2888.     dc.b    'CNC  a$     PUSH p$     SUI  n$     RST  2$     ' ;D4-D7
  2889.     dc.b    'RC$         EXX$        JC   a$     IN   n$     ' ;D8-DB
  2890.     dc.b    'CC   a$     ILLEGAL$    SBI  n$     RST  3$     ' ;DC-DF
  2891.     dc.b    'RPO$        POP  p$     JPO  a$     XTh$        ' ;E0-E3
  2892.     dc.b    'CPO  a$     PUSH p$     ANI  n$     RST  4$     ' ;E4-E7
  2893.     dc.b    'RPE$        PCh$        JPE  a$     XCHG$       ' ;E8-EB
  2894.     dc.b    'CPE  a$     ILLEGAL$    XRI  n$     RST  5$     ' ;EC-FF
  2895.     dc.b    'RP$         POP  p$     JP   a$     DI$         ' ;F0-F3
  2896.     dc.b    'CP   a$     PUSH p$     ORI  n$     RST  6$     ' ;F4-F7
  2897.     dc.b    'RM$         SPh$        JM   a$     EI$         ' ;F8-FB
  2898.     dc.b    'CM   a$     ILLEGAL$    CPI  n$     RST  7$     ' ;FC-FF
  2899.  
  2900. * Mnemonics for Z-80 opcodes C0 through FF
  2901. *  These are interpreted by the same routine as for opcodes 00 through 3F.
  2902. mnopC0z:
  2903.     dc.b    'RET  NZ$    LD   p,(SP)$JP   NZ,a$  JP   a$     ' ;C0-C3
  2904.     dc.b    'CALL NZ,a$  LD   (SP),p$ADD  A,n$   RST  0$     ' ;C4-C7
  2905.     dc.b    'RET  Z$     RET$        JP   Z,a$   ILLEGAL$    ' ;C8-CB
  2906.     dc.b    'CALL Z,a$   CALL a$     ADC  A,n$   RST  8$     ' ;CC-CF
  2907.     dc.b    'RET  NC$    LD   p,(SP)$JP   NC,a$  OUT  n,A$   ' ;D0-D3
  2908.     dc.b    'CALL NC,a$  LD   (SP),p$SUB  A,n$   RST  10$    ' ;D4-D7
  2909.     dc.b    'RET  C$     EXX$        JP   C,a$   IN   A,n$   ' ;D8-DB
  2910.     dc.b    'CALL C,a$   ILLEGAL$    SBC  A,n$   RST  18$    ' ;DC-DF
  2911.     dc.b    'RET  PO$    LD   p,(SP)$JP   PO,a$  EX   (SP),p$' ;E0-E3
  2912.     dc.b    'CALL PO,a$  LD   (SP),p$AND  A,n$   RST  20$    ' ;E4-E7
  2913.     dc.b    'RET  PE$    JP   (p)$   JP   PE,a$  EX   DE,p$  ' ;E8-EB
  2914.     dc.b    'CALL PE,a$  ILLEGAL$    XOR  A,n$   RST  28$    ' ;EC-FF
  2915.     dc.b    'RET  P$     LD   p,(SP)$JP   P,a$   DI$         ' ;F0-F3
  2916.     dc.b    'CALL P,a$   LD   (SP),p$OR   A,n$   RST  30$    ' ;F4-F7
  2917.     dc.b    'RET  M$     LD   SP,h$  JP   M,a$   EI$         ' ;F8-FB
  2918.     dc.b    'CALL M,a$   ILLEGAL$    CP   A,n$   RST  38$    ' ;FC-FF
  2919.  
  2920. * Mnemonics for opcodes CB00 through CB3F -
  2921. *  these are the same for both the 8080 and the Z-80.
  2922. mnopCB08:
  2923. mnopCB0z:
  2924.     dc.b    'RLC  r$ RRC  r$ RL   r$ RR   r$ '    ;CB00-CB1F
  2925.     dc.b    'SLA  r$ SRA  r$ ILLEGAL$SRL  r$ '    ;CB20-CB3F
  2926.  
  2927. * Mnemonics for opcodes CB40 through CBFF -
  2928. *  these are the same for both the 8080 and the Z-80.
  2929. mnopCB48:
  2930. mnopCB4z:
  2931.     dc.b    'BIT  $  RES  $  SET  $  '
  2932.  
  2933. * Mnemonics for 8080 opcodes ED40 through ED7F
  2934. *  These are interpreted by the same routine as for opcodes 00 through 3F.
  2935. mnopE48:
  2936.     dc.b    'IN   q,(C)$ OUT  (C),q$ DSBB p$     SBCD a$     ' ;ED40-ED43
  2937.     dc.b    'NEG$        RETN$       IM0$        MOV  I,A$   ' ;ED44-ED47
  2938.     dc.b    'IN   q,(C)$ OUT  (C),q$ DADC p$     LBCD a$     ' ;ED48-ED4B
  2939.     dc.b    'ILLEGAL$    RETI$       ILLEGAL$    MOV  R,A$   ' ;ED4C-ED4F
  2940.     dc.b    'IN   q,(C)$ OUT  (C),q$ DSBB p$     SDED a$     ' ;ED50-ED53
  2941.     dc.b    'ILLEGAL$    ILLEGAL$    IM1$        MOV  A,I$   ' ;ED54-ED57
  2942.     dc.b    'IN   q,(C)$ OUT  (C),q$ DADC p$     LDED a$     ' ;ED58-ED5B
  2943.     dc.b    'ILLEGAL$    ILLEGAL$    IM2$        MOV  A,R$   ' ;ED5C-ED5F
  2944.     dc.b    'IN   q,(C)$ OUT  (C),q$ DSBB p$     SHLD a$     ' ;ED60-ED63
  2945.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    RRD$        ' ;ED64-ED67
  2946.     dc.b    'IN   q,(C)$ OUT  (C),q$ DADC p$     LHLD a$     ' ;ED68-ED6B
  2947.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    RLD$        ' ;ED6C-ED6F
  2948.     dc.b    'IN   q,(C)$ OUT  (C),q$ DSBB p$     SSPD a$     ' ;ED70-ED73
  2949.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    ILLEGAL$    ' ;ED74-ED77
  2950.     dc.b    'IN   q,(C)$ OUT  (C),q$ DADC p$     LSPD a$     ' ;ED78-ED7B
  2951.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    ILLEGAL$    ' ;ED7C-ED7F
  2952.  
  2953. * Mnemonics for Z-80 opcodes ED40 through ED7F
  2954. *  These are interpreted by the same routine as for opcodes 00 through 3F.
  2955. mnopE4z:
  2956.     dc.b    'IN   q,(C)$ OUT  (C),q$ SBC  HL,p$  LD   (a),p$ ' ;ED40-ED43
  2957.     dc.b    'NEG$        RETN$       IM   0$     LD   I,A$   ' ;ED44-ED47
  2958.     dc.b    'IN   q,(C)$ OUT  (C),q$ ADC  HL,p$  LD   p,(a)$ ' ;ED48-ED4B
  2959.     dc.b    'ILLEGAL$    RETI$       ILLEGAL$    LD   R,A$   ' ;ED4C-ED4F
  2960.     dc.b    'IN   q,(C)$ OUT  (C),q$ SBC  HL,p$  LD   (a),p$ ' ;ED50-ED53
  2961.     dc.b    'ILLEGAL$    ILLEGAL$    IM   1$     LD   A,I$   ' ;ED54-ED57
  2962.     dc.b    'IN   q,(C)$ OUT  (C),q$ ADC  HL,p$  LD   p,(a)$ ' ;ED58-ED5B
  2963.     dc.b    'ILLEGAL$    ILLEGAL$    IM   2$     LD   A,R$   ' ;ED5C-ED5F
  2964.     dc.b    'IN   q,(C)$ OUT  (C),q$ SBC  HL,p$  LD   (a),p$ ' ;ED60-ED63
  2965.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    RRD$        ' ;ED64-ED67
  2966.     dc.b    'IN   q,(C)$ OUT  (C),q$ ADC  HL,p$  LD   p,(a)$ ' ;ED68-ED6B
  2967.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    RLD$        ' ;ED6C-ED6F
  2968.     dc.b    'IN   q,(C)$ OUT  (C),q$ SBC  HL,p$  LD   (a),p$ ' ;ED70-ED73
  2969.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    ILLEGAL$    ' ;ED74-ED77
  2970.     dc.b    'IN   q,(C)$ OUT  (C),q$ ADC  HL,p$  LD   p,(a)$ ' ;ED78-ED7B
  2971.     dc.b    'ILLEGAL$    ILLEGAL$    ILLEGAL$    ILLEGAL$    ' ;ED7C-ED7F
  2972.  
  2973. * Mnemonics for miscellaneous ED-prefix instructions -
  2974. *  these are the same for both the 8080 and the Z-80.
  2975. mnopEA8:
  2976. mnopEAz:
  2977.     dc.b    'LDI$ CPI$ INI$ OUTI$'    ;EDA0-EDA3
  2978.     dc.b    '                    '    ;EDA4-EDA7 (illegal)
  2979.     dc.b    'LDD$ CPD$ IND$ OUTD$'    ;EDA8-EDAB
  2980.     dc.b    '                    '    ;EDAC-EDAF (illegal)
  2981.     dc.b    'LDIR$CPIR$INIR$OTIR$'    ;EDB0-EDB3
  2982.     dc.b    '                    '    ;EDB4-EDB7 (illegal)
  2983.     dc.b    'LDDR$CPDR$INDR$OTDR$'    ;EDB8-EDBB
  2984.  
  2985. * Mnemonic for illegal instructions
  2986. mnopilg dc.b    'ILLEGAL$'
  2987.     page
  2988. *************************************************************************
  2989. *                                    *
  2990. *    Fake FDOS                            *
  2991. *                                    *
  2992. *************************************************************************
  2993.  
  2994. *
  2995. * Fake BDOS for target system
  2996. *
  2997. fdos    dc.b    tHLT,0,tRET    ;BIOS jump table
  2998.     dc.b    tJMP,$33,$FF    ;Warm boot
  2999.     dc.b    tJMP,$36,$FF    ;Console status
  3000.     dc.b    tJMP,$39,$FF    ;Console input
  3001.     dc.b    tJMP,$3C,$FF    ;Console output
  3002.     dc.b    tJMP,$3F,$FF    ;List output
  3003.     dc.b    tJMP,$42,$FF    ;Punch output
  3004.     dc.b    tJMP,$45,$FF    ;Reader input
  3005.     dc.b    tJMP,$48,$FF    ;Home disk
  3006.     dc.b    tJMP,$4B,$FF    ;Select disk
  3007.     dc.b    tJMP,$4E,$FF    ;Set track
  3008.     dc.b    tJMP,$51,$FF    ;Set sector
  3009.     dc.b    tJMP,$54,$FF    ;Set DMA address
  3010.     dc.b    tJMP,$57,$FF    ;Read
  3011.     dc.b    tJMP,$5A,$FF    ;Write
  3012.     dc.b    tJMP,$5D,$FF    ;Get list device status
  3013.     dc.b    tJMP,$60,$FF    ;Sector translation
  3014.  
  3015. *
  3016. * Fake BIOS for target system
  3017. *
  3018.     dc.b    tHLT,1,tRET    ;Warm boot
  3019.     dc.b    tHLT,2,tRET    ;Console status
  3020.     dc.b    tHLT,3,tRET    ;Console input
  3021.     dc.b    tHLT,4,tRET    ;Console output
  3022.     dc.b    tHLT,5,tRET    ;List output
  3023.     dc.b    tHLT,6,tRET    ;Punch output
  3024.     dc.b    tHLT,7,tRET    ;Reader input
  3025.     dc.b    tHLT,8,tRET    ;Home disk *
  3026.     dc.b    tHLT,9,tRET    ;Select disk *
  3027.     dc.b    tHLT,10,tRET    ;Set track *
  3028.     dc.b    tHLT,11,tRET    ;Set sector *
  3029.     dc.b    tHLT,12,tRET    ;Set DMA address *
  3030.     dc.b    tHLT,13,tRET    ;Read *
  3031.     dc.b    tHLT,14,tRET    ;Write *
  3032.     dc.b    tHLT,15,tRET    ;Get list device status *
  3033.     dc.b    tHLT,16,tRET    ;Sector translation *
  3034.  
  3035. *
  3036. * Fake Disk Parameter Block
  3037. *
  3038. fakedpb    dc.b    11,0        ;SPT (sectors per track)
  3039.     dc.b    4        ;BSH (block shift to record number)
  3040.     dc.b    15        ;BLM (block number mask to record no.)
  3041.     dc.b    0        ;EXM (logical->physical extent shift)
  3042.     dc.b    439&255,439/256    ;DSM (highest allocation block number)
  3043.     dc.b    255,0        ;DRM (highest directory entry number)
  3044.     dc.b    $F0,0        ;AL0, AL1 (initial allocation vector)
  3045.     dc.b    64,0        ;CKS (size of directory check area)
  3046.     dc.b    0,0        ;OFF (offset, number of reserved tracks)
  3047.  
  3048. *
  3049. * Fake Disk Block Allocation Table
  3050. *
  3051. fakealv    dcb.b    21,$FF
  3052.     dc.b    %11111100
  3053.     dcb.b    10,0
  3054.  
  3055. fdoslen equ    *-fdos
  3056.  
  3057. *
  3058. * BDOS function vector table
  3059. *
  3060.     cnop    0,4
  3061. bdostab dc.l    bdos00,bdos01,bdos02,bdos03,bdos04,bdos05,bdos06,bdos07
  3062.     dc.l    bdos08,bdos09,bdos10,bdos11,bdos12,bdos13,bdos14,bdos15
  3063.     dc.l    bdos16,bdos17,bdos18,bdos19,bdos20,bdos21,bdos22,bdos23
  3064.     dc.l    bdos24,bdos25,bdos26,bdos27,bdos28,bdos29,bdos30,bdos31
  3065.     dc.l    bdos32,bdos33,bdos34,bdos35,bdos36
  3066. bdostabn:
  3067.  
  3068. *
  3069. * BIOS function vector table
  3070. *
  3071.     cnop    0,4
  3072. biostab dc.l    bdosfn,bios01,bios02,bios03,bios04,bios05,bios06,bios07
  3073.     dc.l    bios08,bios09,bios10,bios11,bios12,bios13,bios14,bios15
  3074. biostabn:
  3075.  
  3076. null    dc.b    0        ;Null string
  3077.     page
  3078. *************************************************************************
  3079. *                                    *
  3080. *    Variable storage                        *
  3081. *                                    *
  3082. *************************************************************************
  3083.  
  3084.     bss    bss
  3085.  
  3086. * File information block - must be on a 4-byte boundary!
  3087. fib:
  3088. fibkey    ds.l    1
  3089. fibtype ds.l    1    ;Type (file if negative, directory if positive)
  3090. fibname ds.b    108    ;File name (null-terminated)
  3091. fibprot ds.l    1    ;Protection mask
  3092. fibent    ds.l    1
  3093. fibsize ds.l    1    ;Number of bytes in file
  3094. fibblks ds.l    1    ;Number of blocks in file
  3095. fibdays ds.l    1    ;Date stamp - number of days since Jan. 1, 1978
  3096. fibmins ds.l    1    ;Date stamp - number of minutes past midnight
  3097. fibtick ds.l    1    ;Date stamp - number of ticks past minute
  3098. fibcmt    ds.b    116    ;Comments (null-terminated)
  3099.  
  3100. * InfoData structure
  3101. InfoData:
  3102. id_NumSoftErrors ds.l    1    ;number of soft errors on disk
  3103. id_UnitNumber     ds.l    1    ;Which unit disk is (was) mounted on
  3104. id_DiskState     ds.l    1    ;See defines below
  3105. id_NumBlocks     ds.l    1    ;Number of blocks on disk
  3106. id_NumBlocksUsed ds.l    1    ;Number of block in use
  3107. id_BytesPerBlock ds.l    1
  3108. id_DiskType     ds.l    1    ;Disk Type code
  3109. id_VolumeNode     ds.l    1    ;BCPL pointer to volume node
  3110. id_InUse     ds.l    1    ;Flag, zero if not in use
  3111. id_SIZEOF     equ    36
  3112.  
  3113. * Miscellaneous storage areas
  3114. savesp    ds.l    1        ;Stack pointer save area
  3115. _SysBase ds.l    1        ;Copy of _AbsExecBase
  3116. _DOSBase ds.l    1        ;Pointer to dos.library
  3117. stdin    ds.l    1        ;Keyboard handle (stdin)
  3118. stdout    ds.l    1        ;Screen handle (stdout)
  3119. rawhand ds.l    1        ;RAW: file handle
  3120. prthand ds.l    1        ;PRT:RAW file handle
  3121. handles ds.l    8*4        ;File handle (or zero) plus 12 bytes of FCB
  3122. handlen:            ;End of file handle table
  3123. dmaaddr ds.l    1        ;Current DMA address
  3124. comend    ds.l    1        ;End of .COM file name on command line
  3125. dtstamp ds.l    3        ;Date and time stamp
  3126. rpport    ds.l    1        ;Serial input message port
  3127. wpport    ds.l    1        ;Serial output message port
  3128. baud    ds.l    1        ;New baud rate for "setbaud"
  3129. bits    ds.b    1        ;Number of data bits
  3130. charin    ds.b    1        ;Current input character
  3131. charinb ds.b    1        ;Serial input buffer
  3132. charout ds.b    1        ;Current output character
  3133. frstset ds.b    1        ;$80 after first call to "setbaud"
  3134. cmdline ds.b    128        ;Command line
  3135. cmdlinen:            ;End of command line
  3136. comname ds.b    20        ;Name of file to load
  3137. comnamen:            ;End of file name
  3138. opnname ds.b    24        ;File name for OPEN or RENAME
  3139. renname ds.b    24        ;New file name for RENAME
  3140. srchnam ds.b    11        ;CP/M file name for search first/next
  3141. ext17    ds.w    1        ;Extent counter for search first/next
  3142. newrega ds.b    1        ;BIOS/BDOS accumulator work area
  3143. workbuf ds.b    80        ;Work buffer for "pstring" (including $)
  3144. workbufn:            ;End of work buffer
  3145. strbuf    ds.b    2048        ;String output buffer
  3146. strbufn ds.b    8        ;"strbuf" overflow area - must follow "strbuf"!
  3147. strptr    ds.l    1        ;Current position in "strbuf"
  3148. escbuf    ds.b    8        ;Translated escape sequence
  3149. esclen    ds.w    1        ;Number of bytes saved in "escbuf"
  3150. cmdflag ds.b    1        ;Take program name from command line.
  3151. quitflg ds.b    1        ;"quitprg" exit flag
  3152. testdol ds.b    1        ;"pstring" should test for leading $
  3153. insflag ds.b    1        ;We're in insert mode.
  3154. dumpcnt ds.b    1        ;"dump" counter for pausing
  3155. traceit ds.b    1        ;-t (trace) flag was set on command line
  3156. btrcflg ds.b    1        ;Trace BIOS/BDOS calls.
  3157. bufflag ds.b    1        ;Console output is buffered.
  3158. z80flag ds.b    1        ;Display Z-80 mnemonics in instruction trace.
  3159. opcode    ds.b    1        ;Current opcode (used for tracing)
  3160. prefix    ds.b    1        ;Instruction prefix (DD or FD)
  3161. fcbptr    ds.l    1        ;Pointer to current FCB
  3162. listopn ds.b    1        ;The list device is open.
  3163. builtin ds.b    1        ;1 = USER command, 2 = SAVE command
  3164. acmap    ds.w    1        ;Active drive map
  3165. romap    ds.w    1        ;Read-only map
  3166. newdmap ds.w    1        ;Map bit from "mapdrv"
  3167.  
  3168. *
  3169. * Serial port read request
  3170. *
  3171.     ds.l    0
  3172. readreq     ;struct IOExtSer
  3173.         ;struct IOStdReq
  3174.         ;struct Message
  3175.     ds.b    14    ;struct Node
  3176. r_ReplyPort    ds.l 1    ;Pointer to MsgPort (message reply port)
  3177. r_MLength ds.w    1    ;Message length in bytes
  3178.         ; End of struct Message
  3179.     ds.l    1    ;Pointer to device node
  3180.     ds.l    1    ;Pointer to Unit (driver private)
  3181. r_Command ds.w    1    ;Device command
  3182.     ds.b    1    ;io_Flags
  3183.     ds.b    1    ;Error or warning number
  3184.         ; End of struct IOReq - IOStdReq continues...
  3185. r_Actual ds.l    1    ;Actual number of bytes transferred
  3186. r_Length ds.l    1    ;Requested number of bytes transferred
  3187. r_Data    ds.l    1    ;Points to data area.
  3188. r_Offset ds.l    1    ;Offset for block-structured devices
  3189.         ; End of struct IOStdReq
  3190. r_CtlChar ds.l    1    ;control char's (order = xON,xOFF,INQ,ACK)
  3191. r_RBufLen ds.l    1    ;length in bytes of serial port's read buffer
  3192. r_ExtFlags ds.l 1    ;additional serial flags (see bitdefs below)
  3193. r_Baud    ds.l    1    ;baud rate requested (true baud)
  3194.     ds.l    1    ;duration of break signal in MICROseconds
  3195.         ;struct IOTArray termination character array
  3196. r_ReadLen ds.b    1    ;bits per read character (# of bits)
  3197. r_WriteLen ds.b 1    ;bits per write character (# of bits)
  3198. r_StopBits ds.b 1    ;stopbits for read (# of bits)
  3199. r_SerFlags ds.b 1    ;see SerFlags bit definitions below
  3200. r_Status ds.w    1    ;status of serial port
  3201. rsize    equ    *-readreq
  3202.  
  3203. *
  3204. * Serial port write request
  3205. *
  3206.     ds.l    0
  3207. writreq     ;struct IOExtSer
  3208.         ;struct IOStdReq
  3209.         ;struct Message
  3210.     ds.b    14    ;struct Node
  3211. w_ReplyPort    ds.l 1    ;Pointer to MsgPort (message reply port)
  3212. w_MLength ds.w    1    ;Message length in bytes
  3213.         ; End of struct Message
  3214.     ds.l    1    ;Pointer to device node
  3215.     ds.l    1    ;Pointer to Unit (driver private)
  3216. w_Command ds.w    1    ;Device command
  3217.     ds.b    1    ;io_Flags
  3218.     ds.b    1    ;Error or warning number
  3219.         ; End of struct IOReq - IOStdReq continues...
  3220. w_Actual ds.l    1    ;Actual number of bytes transferred
  3221. w_Length ds.l    1    ;Requested number of bytes transferred
  3222. w_Data    ds.l    1    ;Points to data area.
  3223. w_Offset ds.l    1    ;Offset for block-structured devices
  3224.         ; End of struct IOStdReq
  3225. w_CtlChar ds.l    1    ;control char's (order = xON,xOFF,INQ,ACK)
  3226. w_RBufLen ds.l    1    ;length in bytes of serial port's read buffer
  3227. w_ExtFlags ds.l 1    ;additional serial flags (see bitdefs below)
  3228. w_Baud    ds.l    1    ;baud rate requested (true baud)
  3229.     ds.l    1    ;duration of break signal in MICROseconds
  3230.         ;struct IOTArray termination character array
  3231. w_ReadLen ds.b    1    ;bits per read character (# of bits)
  3232. w_WriteLen ds.b 1    ;bits per write character (# of bits)
  3233. w_StopBits ds.b 1    ;stopbits for read (# of bits)
  3234. w_SerFlags ds.b 1    ;see SerFlags bit definitions below
  3235. w_Status ds.w    1    ;status of serial port, as follows:
  3236. wsize    equ    *-writreq
  3237. *           BIT    ACTIVE    FUNCTION
  3238. *            0     low    busy
  3239. *            1     low    paper out
  3240. *            2     low    select
  3241. *            3     low    Data Set Ready
  3242. *            4     low    Clear To Send
  3243. *            5     low    Carrier Detect
  3244. *            6     low    Ready To Send
  3245. *            7     low    Data Terminal Ready
  3246. *            8     high    read overrun
  3247. *            9     high    break sent
  3248. *           10     high    break received
  3249. *           11     high    transmit x-OFFed       
  3250. *           12     high    receive x-OFFed       
  3251. *        13-15        reserved
  3252.  
  3253. *************************************************************************
  3254. *                                    *
  3255. *    Target processor's address space                *
  3256. *                                    *
  3257. *************************************************************************
  3258.  
  3259.     even
  3260.  
  3261. registers ds.b    22        ;Actual storage for Z-80's other registers
  3262. target    ds.b    $10000        ;Z-80's universe
  3263.  
  3264.     end
  3265.